diff --git a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml
index d46d5e0f0345..f8f3677c7687 100644
--- a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml
+++ b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml
@@ -190,6 +190,13 @@
services.aesmd.
+
+
+ bird-lg,
+ a BGP looking glass for Bird Routing. Available as
+ services.bird-lg.
+
+
rootless
diff --git a/nixos/doc/manual/release-notes/rl-2205.section.md b/nixos/doc/manual/release-notes/rl-2205.section.md
index edb3758dd2f1..32dfb679b54a 100644
--- a/nixos/doc/manual/release-notes/rl-2205.section.md
+++ b/nixos/doc/manual/release-notes/rl-2205.section.md
@@ -61,6 +61,8 @@ In addition to numerous new and upgraded packages, this release has the followin
- [aesmd](https://github.com/intel/linux-sgx#install-the-intelr-sgx-psw), the Intel SGX Architectural Enclave Service Manager. Available as [services.aesmd](#opt-services.aesmd.enable).
+- [bird-lg](https://github.com/xddxdd/bird-lg-go), a BGP looking glass for Bird Routing. Available as [services.bird-lg](#opt-services.bird-lg.package).
+
- [rootless Docker](https://docs.docker.com/engine/security/rootless/), a `systemd --user` Docker service which runs without root permissions. Available as [virtualisation.docker.rootless.enable](options.html#opt-virtualisation.docker.rootless.enable).
- [matrix-conduit](https://conduit.rs/), a simple, fast and reliable chat server powered by matrix. Available as [services.matrix-conduit](option.html#opt-services.matrix-conduit.enable).
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 2607e99d8459..7ca90fc3ec34 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -733,6 +733,7 @@
./services/networking/bitcoind.nix
./services/networking/autossh.nix
./services/networking/bird.nix
+ ./services/networking/bird-lg.nix
./services/networking/bitlbee.nix
./services/networking/blockbook-frontend.nix
./services/networking/blocky.nix
diff --git a/nixos/modules/services/networking/bird-lg.nix b/nixos/modules/services/networking/bird-lg.nix
new file mode 100644
index 000000000000..515ef38608b4
--- /dev/null
+++ b/nixos/modules/services/networking/bird-lg.nix
@@ -0,0 +1,269 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.bird-lg;
+in
+{
+ options = {
+ services.bird-lg = {
+ package = mkOption {
+ type = types.package;
+ default = pkgs.bird-lg;
+ defaultText = literalExpression "pkgs.bird-lg";
+ description = "The Bird Looking Glass package to use.";
+ };
+
+ user = mkOption {
+ type = types.str;
+ default = "bird-lg";
+ description = "User to run the service.";
+ };
+
+ group = mkOption {
+ type = types.str;
+ default = "bird-lg";
+ description = "Group to run the service.";
+ };
+
+ frontend = {
+ enable = mkEnableOption "Bird Looking Glass Frontend Webserver";
+
+ listenAddress = mkOption {
+ type = types.str;
+ default = "127.0.0.1:5000";
+ description = "Address to listen on.";
+ };
+
+ proxyPort = mkOption {
+ type = types.port;
+ default = 8000;
+ description = "Port bird-lg-proxy is running on.";
+ };
+
+ domain = mkOption {
+ type = types.str;
+ default = "";
+ example = "dn42.lantian.pub";
+ description = "Server name domain suffixes.";
+ };
+
+ servers = mkOption {
+ type = types.listOf types.str;
+ default = [ ];
+ example = [ "gigsgigscloud" "hostdare" ];
+ description = "Server name prefixes.";
+ };
+
+ whois = mkOption {
+ type = types.str;
+ default = "whois.verisign-grs.com";
+ description = "Whois server for queries.";
+ };
+
+ dnsInterface = mkOption {
+ type = types.str;
+ default = "asn.cymru.com";
+ description = "DNS zone to query ASN information.";
+ };
+
+ bgpMapInfo = mkOption {
+ type = types.listOf types.str;
+ default = [ "asn" "as-name" "ASName" "descr" ];
+ description = "Information displayed in bgpmap.";
+ };
+
+ titleBrand = mkOption {
+ type = types.str;
+ default = "Bird-lg Go";
+ description = "Prefix of page titles in browser tabs.";
+ };
+
+ netSpecificMode = mkOption {
+ type = types.str;
+ default = "";
+ example = "dn42";
+ description = "Apply network-specific changes for some networks.";
+ };
+
+ protocolFilter = mkOption {
+ type = types.listOf types.str;
+ default = [ ];
+ example = [ "ospf" ];
+ description = "Information displayed in bgpmap.";
+ };
+
+ nameFilter = mkOption {
+ type = types.str;
+ default = "";
+ example = "^ospf";
+ description = "Protocol names to hide in summary tables (RE2 syntax),";
+ };
+
+ timeout = mkOption {
+ type = types.int;
+ default = 120;
+ description = "Time before request timed out, in seconds.";
+ };
+
+ navbar = {
+ brand = mkOption {
+ type = types.str;
+ default = "Bird-lg Go";
+ description = "Brand to show in the navigation bar .";
+ };
+
+ brandURL = mkOption {
+ type = types.str;
+ default = "/";
+ description = "URL of the brand to show in the navigation bar.";
+ };
+
+ allServers = mkOption {
+ type = types.str;
+ default = "ALL Servers";
+ description = "Text of 'All server' button in the navigation bar.";
+ };
+
+ allServersURL = mkOption {
+ type = types.str;
+ default = "all";
+ description = "URL of 'All servers' button.";
+ };
+ };
+
+ extraArgs = mkOption {
+ type = types.lines;
+ default = "";
+ description = "
+ Extra parameters documented here.
+ ";
+ };
+ };
+
+ proxy = {
+ enable = mkEnableOption "Bird Looking Glass Proxy";
+
+ listenAddress = mkOption {
+ type = types.str;
+ default = "127.0.0.1:8000";
+ description = "Address to listen on.";
+ };
+
+ allowedIPs = mkOption {
+ type = types.listOf types.str;
+ default = [ ];
+ example = [ "192.168.25.52" "192.168.25.53" ];
+ description = "List of IPs to allow (default all allowed).";
+ };
+
+ birdSocket = mkOption {
+ type = types.str;
+ default = "/run/bird.ctl";
+ example = "/var/run/bird/bird.ctl";
+ description = "Bird control socket path.";
+ };
+
+ traceroute = {
+ binary = mkOption {
+ type = types.str;
+ default = "${pkgs.traceroute}/bin/traceroute";
+ defaultText = literalExpression ''"''${pkgs.traceroute}/bin/traceroute"'';
+ description = "Traceroute's binary path.";
+ };
+
+ rawOutput = mkOption {
+ type = types.bool;
+ default = false;
+ description = "Display traceroute output in raw format.";
+ };
+ };
+
+ extraArgs = mkOption {
+ type = types.lines;
+ default = "";
+ description = "
+ Extra parameters documented here.
+ ";
+ };
+ };
+ };
+ };
+
+ ###### implementation
+
+ config = {
+ systemd.services = {
+ bird-lg-frontend = mkIf cfg.frontend.enable {
+ enable = true;
+ after = [ "network.target" ];
+ wantedBy = [ "multi-user.target" ];
+ description = "Bird Looking Glass Frontend Webserver";
+ serviceConfig = {
+ Type = "simple";
+ Restart = "on-failure";
+ ProtectSystem = "full";
+ ProtectHome = "yes";
+ MemoryDenyWriteExecute = "yes";
+ User = cfg.user;
+ Group = cfg.group;
+ };
+ script = ''
+ ${cfg.package}/bin/frontend \
+ --servers ${concatStringsSep "," cfg.frontend.servers } \
+ --domain ${cfg.frontend.domain} \
+ --listen ${cfg.frontend.listenAddress} \
+ --proxy-port ${toString cfg.frontend.proxyPort} \
+ --whois ${cfg.frontend.whois} \
+ --dns-interface ${cfg.frontend.dnsInterface} \
+ --bgpmap-info ${concatStringsSep "," cfg.frontend.bgpMapInfo } \
+ --title-brand ${cfg.frontend.titleBrand} \
+ --navbar-brand ${cfg.frontend.navbar.brand} \
+ --navbar-brand-url ${cfg.frontend.navbar.brandURL} \
+ --navbar-all-servers ${cfg.frontend.navbar.allServers} \
+ --navbar-all-url ${cfg.frontend.navbar.allServersURL} \
+ --net-specific-mode ${cfg.frontend.netSpecificMode} \
+ --protocol-filter ${concatStringsSep "," cfg.frontend.protocolFilter } \
+ --name-filter ${cfg.frontend.nameFilter} \
+ --time-out ${toString cfg.frontend.timeout} \
+ ${cfg.frontend.extraArgs}
+ '';
+ };
+
+ bird-lg-proxy = mkIf cfg.proxy.enable {
+ enable = true;
+ after = [ "network.target" ];
+ wantedBy = [ "multi-user.target" ];
+ description = "Bird Looking Glass Proxy";
+ serviceConfig = {
+ Type = "simple";
+ Restart = "on-failure";
+ ProtectSystem = "full";
+ ProtectHome = "yes";
+ MemoryDenyWriteExecute = "yes";
+ User = cfg.user;
+ Group = cfg.group;
+ };
+ script = ''
+ ${cfg.package}/bin/proxy \
+ --allowed ${concatStringsSep "," cfg.proxy.allowedIPs } \
+ --bird ${cfg.proxy.birdSocket} \
+ --listen ${cfg.proxy.listenAddress} \
+ --traceroute_bin ${cfg.proxy.traceroute.binary}
+ --traceroute_raw ${boolToString cfg.proxy.traceroute.rawOutput}
+ ${cfg.proxy.extraArgs}
+ '';
+ };
+ };
+ users = mkIf (cfg.frontend.enable || cfg.proxy.enable) {
+ groups."bird-lg" = mkIf (cfg.group == "bird-lg") { };
+ users."bird-lg" = mkIf (cfg.user == "bird-lg") {
+ description = "Bird Looking Glass user";
+ extraGroups = lib.optionals (config.services.bird2.enable) [ "bird2" ];
+ group = cfg.group;
+ isSystemUser = true;
+ };
+ };
+ };
+}
diff --git a/pkgs/servers/bird-lg/default.nix b/pkgs/servers/bird-lg/default.nix
new file mode 100644
index 000000000000..f5294c2a191a
--- /dev/null
+++ b/pkgs/servers/bird-lg/default.nix
@@ -0,0 +1,42 @@
+{ buildGoModule, fetchFromGitHub, lib, symlinkJoin }:
+let
+ generic = { modRoot, vendorSha256 }:
+ buildGoModule rec {
+ pname = "bird-lg-${modRoot}";
+ version = "unstable-2022-05-08";
+
+ src = fetchFromGitHub {
+ owner = "xddxdd";
+ repo = "bird-lg-go";
+ rev = "348295b9aa954a92df2cf6b1179846a9486dafc0";
+ sha256 = "sha256-2t8ZP9Uc0sJlqWiJMq3MVoARfMKsuTXJkuOid0oWgyY=";
+ };
+
+ doDist = false;
+
+ ldflags = [
+ "-s"
+ "-w"
+ ];
+
+ inherit modRoot vendorSha256;
+
+ meta = with lib; {
+ description = "Bird Looking Glass";
+ homepage = "https://github.com/xddxdd/bird-lg-go";
+ license = licenses.gpl3Plus;
+ maintainers = with maintainers; [ tchekda ];
+ };
+ };
+
+ bird-lg-frontend = generic {
+ modRoot = "frontend";
+ vendorSha256 = "sha256-WKuVGiSV5LZrJ8/672TRN6tZNQxdCktHV6nx0ZxCP4A=";
+ };
+
+ bird-lg-proxy = generic {
+ modRoot = "proxy";
+ vendorSha256 = "sha256-7LZeCY4xSxREsQ+Dc2XSpu2ZI8CLE0mz0yoThP7/OO4=";
+ };
+in
+symlinkJoin { name = "bird-lg"; paths = [ bird-lg-frontend bird-lg-proxy ]; }
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index a492aed9cd1c..98c681368583 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -21610,6 +21610,8 @@ with pkgs;
bird = callPackage ../servers/bird { };
+ bird-lg = callPackage ../servers/bird-lg { };
+
bloat = callPackage ../servers/bloat { };
bosun = callPackage ../servers/monitoring/bosun { };