{
  description = "tsnet-proxy: proxy onto tsnet";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
  };

  outputs = {
    self,
    nixpkgs,
  }: let
    eachSystem = f:
      nixpkgs.lib.genAttrs ["x86_64-linux" "aarch64-linux"] (system:
        f rec {
          inherit system;
          pkgs = nixpkgs.legacyPackages.${system};
          inherit (pkgs) callPackage;
        });
  in {
    packages = eachSystem ({callPackage, pkgs, ...}: {
      default = callPackage ./. {};
      get-authkey = pkgs.tailscale.overrideAttrs {
        subPackages = ["cmd/get-authkey"];
        outputs = ["out"];
        postInstall = "";
      };
    });
    devShells = eachSystem ({callPackage, ...}: {
      default = callPackage ./shell.nix {};
    });
    nixosModules.default = {
      config,
      pkgs,
      lib,
      ...
    }: {
      options.services.bluepython508.tsnet-proxy = with lib;
      with types; {
        clientId = mkOption {
          type = str;
        };
        clientSecretFile = mkOption {
          type = str;
        };
        tags = mkOption {type = listOf str;};
        proxies = mkOption {
          type = attrsOf (submodule ({config, ...}: {
            options = let
              proto = enum ["udp" "tcp" "unix" "tls"];
            in {
              enable = mkOption {
                type = bool;
                default = true;
              };
              forwards = mkOption {
                type = listOf (submodule {
                  options = {
                    proto = mkOption {type = proto;};
                    port = mkOption {type = port;};
                    dest = mkOption {type = str;};
                  };
                });
              };
            };
          }));
        };
      };
      config.bluepython508.impermanence.local.directories = lib.mapAttrsToList (key: _: "/var/lib/private/tsnet-proxy-${key}") config.services.bluepython508.tsnet-proxy.proxies;
      config.systemd.services = let
        cfg = config.services.bluepython508.tsnet-proxy;
      in
        lib.mapAttrs' (hostname: {
          forwards,
          enable,
          ...
        }: let
          name = "tsnet-proxy-${hostname}";
        in {
          inherit name;
          value = {
            inherit enable;
            script = ''
              TS_AUTHKEY=$(cat $RUNTIME_DIRECTORY/authkey) ${lib.getExe self.packages.${pkgs.system}.default} ${hostname} ${lib.concatMapStringsSep " " ({proto, port, dest}: "${proto}:${toString port}:${dest}") forwards}
            '';
            wantedBy = ["multi-user.target"];
            wants = ["network-online.target"];
            after = ["network-online.target"];
            serviceConfig = {
              DynamicUser = true;
              RuntimeDirectory = name;
              StateDirectory = name;
              ExecStartPre = "!${pkgs.writeShellScript "get-authkey" ''
                set -e
                TS_API_CLIENT_ID=${cfg.clientId} TS_API_CLIENT_SECRET=$(cat ${cfg.clientSecretFile}) ${self.packages.${pkgs.system}.get-authkey}/bin/get-authkey -ephemeral -tags ${lib.concatStringsSep "," cfg.tags} > $RUNTIME_DIRECTORY/authkey
                chown ${name}:${name} $RUNTIME_DIRECTORY/authkey
              ''}";
            };
          };
        })
        cfg.proxies;
    };
  };
}
