summary refs log blame commit diff
path: root/nixos/modules/services/networking/quagga.nix
blob: 5acdd5af8f8f41b2b5e56cedec8ace1c341b871f (plain) (tree)
































































































                                                                               
             
     











                                                                
          
        


                                                                     

















                                                                                  
                                              

















































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

with lib;

let

  cfg = config.services.quagga;

  services = [ "babel" "bgp" "isis" "ospf6" "ospf" "pim" "rip" "ripng" ];
  allServices = services ++ [ "zebra" ];

  isEnabled = service: cfg.${service}.enable;

  daemonName = service: if service == "zebra" then service else "${service}d";

  configFile = service:
    let
      scfg = cfg.${service};
    in
      if scfg.configFile != null then scfg.configFile
      else pkgs.writeText "${daemonName service}.conf"
        ''
          ! Quagga ${daemonName service} configuration
          !
          hostname ${config.networking.hostName}
          log syslog
          service password-encryption
          !
          ${scfg.config}
          !
          end
        '';

  serviceOptions = service:
    {
      enable = mkEnableOption "the Quagga ${toUpper service} routing protocol";

      configFile = mkOption {
        type = types.nullOr types.path;
        default = null;
        example = "/etc/quagga/${daemonName service}.conf";
        description = ''
          Configuration file to use for Quagga ${daemonName service}.
          By default the NixOS generated files are used.
        '';
      };

      config = mkOption {
        type = types.lines;
        default = "";
        example =
          let
            examples = {
              rip = ''
                router rip
                  network 10.0.0.0/8
              '';

              ospf = ''
                router ospf
                  network 10.0.0.0/8 area 0
              '';

              bgp = ''
                router bgp 65001
                  neighbor 10.0.0.1 remote-as 65001
              '';
            };
          in
            examples.${service} or "";
        description = ''
          ${daemonName service} configuration statements.
        '';
      };

      vtyListenAddress = mkOption {
        type = types.str;
        default = "127.0.0.1";
        description = ''
          Address to bind to for the VTY interface.
        '';
      };

      vtyListenPort = mkOption {
        type = types.nullOr types.int;
        default = null;
        description = ''
          TCP Port to bind to for the VTY interface.
        '';
      };
    };

in

{

  ###### interface
  imports = [
    {
      options.services.quagga = {
        zebra = (serviceOptions "zebra") // {
          enable = mkOption {
            type = types.bool;
            default = any isEnabled services;
            description = ''
              Whether to enable the Zebra routing manager.

              The Zebra routing manager is automatically enabled
              if any routing protocols are configured.
            '';
          };
        };
      };
    }
    { options.services.quagga = (genAttrs services serviceOptions); }
  ];

  ###### implementation

  config = mkIf (any isEnabled allServices) {

    environment.systemPackages = [
      pkgs.quagga               # for the vtysh tool
    ];

    users.users.quagga = {
      description = "Quagga daemon user";
      isSystemUser = true;
      group = "quagga";
    };

    users.groups = {
      quagga = {};
      # Members of the quaggavty group can use vtysh to inspect the Quagga daemons
      quaggavty = { members = [ "quagga" ]; };
    };

    systemd.services =
      let
        quaggaService = service:
          let
            scfg = cfg.${service};
            daemon = daemonName service;
          in
            nameValuePair daemon ({
              wantedBy = [ "multi-user.target" ];
              restartTriggers = [ (configFile service) ];

              serviceConfig = {
                Type = "forking";
                PIDFile = "/run/quagga/${daemon}.pid";
                ExecStart = "@${pkgs.quagga}/libexec/quagga/${daemon} ${daemon} -d -f ${configFile service}"
                  + optionalString (scfg.vtyListenAddress != "") " -A ${scfg.vtyListenAddress}"
                  + optionalString (scfg.vtyListenPort != null) " -P ${toString scfg.vtyListenPort}";
                ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
                Restart = "on-abort";
              };
            } // (
              if service == "zebra" then
                {
                  description = "Quagga Zebra routing manager";
                  unitConfig.Documentation = "man:zebra(8)";
                  after = [ "network.target" ];
                  preStart = ''
                    install -m 0755 -o quagga -g quagga -d /run/quagga

                    ${pkgs.iproute}/bin/ip route flush proto zebra
                  '';
                }
              else
                {
                  description = "Quagga ${toUpper service} routing daemon";
                  unitConfig.Documentation = "man:${daemon}(8) man:zebra(8)";
                  bindsTo = [ "zebra.service" ];
                  after = [ "network.target" "zebra.service" ];
                }
            ));
       in
         listToAttrs (map quaggaService (filter isEnabled allServices));

  };

  meta.maintainers = with lib.maintainers; [ tavyc ];

}