Unverified Commit 66262655 authored by nixpkgs-ci[bot]'s avatar nixpkgs-ci[bot] Committed by GitHub
Browse files

Merge master into staging-next

parents aa220955 36ced8de
Loading
Loading
Loading
Loading
+27 −17
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ runs:
        PIN_BUMP_SHA: ${{ inputs.untrusted-pin-bump }}
      with:
        script: |
          const { rm, writeFile } = require('node:fs/promises')
          const { spawn } = require('node:child_process')
          const { join } = require('node:path')

@@ -55,10 +56,19 @@ runs:
            return pinned.pins.nixpkgs.revision
          }

          const pin_bump_sha = process.env.PIN_BUMP_SHA
          // Getting the pin-bump diff via the API avoids issues with `git fetch`
          // thin-packs not having enough base objects to be applied locally.
          // Returns a unified diff suitable for `git apply`.
          async function getPinBumpDiff(ref) {
            const { data } = await github.rest.repos.getCommit({
              mediaType: { format: 'diff' },
              ...context.repo,
              ref,
            })
            return data
          }

          // When dealing with a pin bump commit, we need `--depth=2` to view & apply its diff
          const depth = pin_bump_sha ? 2 : 1
          const pin_bump_sha = process.env.PIN_BUMP_SHA

          const commits = [
            {
@@ -76,17 +86,14 @@ runs:
            {
              sha: await getPinnedSha(process.env.TARGET_SHA),
              path: 'trusted-pinned'
            },
            {
              sha: pin_bump_sha
            }
          ].filter(({ sha }) => Boolean(sha))

          console.log('Fetching the following commits:', commits)
          console.log('Checking out the following commits:', commits)

          // Fetching all commits at once is much faster than doing multiple checkouts.
          // This would fail without --refetch, because the we had a partial clone before, but changed it above.
          await run('git', 'fetch', `--depth=${depth}`, '--refetch', 'origin', ...(commits.map(({ sha }) => sha)))
          await run('git', 'fetch', '--depth=1', '--refetch', 'origin', ...(commits.map(({ sha }) => sha)))

          // Checking out onto tmpfs takes 1s and is faster by at least factor 10x.
          await run('mkdir', 'nixpkgs')
@@ -101,9 +108,7 @@ runs:

          // Create all worktrees in parallel.
          await Promise.all(
            commits
              .filter(({ path }) => Boolean(path))
              .map(async ({ sha, path }) => {
            commits.map(async ({ sha, path }) => {
              await run('git', 'worktree', 'add', join('nixpkgs', path), sha, '--no-checkout')
              await run('git', '-C', join('nixpkgs', path), 'sparse-checkout', 'disable')
              await run('git', '-C', join('nixpkgs', path), 'checkout', '--progress')
@@ -112,9 +117,12 @@ runs:

          // Apply pin bump to untrusted worktree
          if (pin_bump_sha) {
            console.log('Applying untrusted ci/pinned.json bump:', pin_bump_sha)
            console.log('Fetching ci/pinned.json bump commit:', pin_bump_sha)
            await writeFile('pin-bump.patch', await getPinBumpDiff(pin_bump_sha))

            console.log('Applying untrusted ci/pinned.json bump to ./nixpkgs/untrusted')
            try {
              await run('git', '-C', join('nixpkgs', 'untrusted'), 'cherry-pick', '--no-commit', pin_bump_sha)
              await run('git', '-C', join('nixpkgs', 'untrusted'), 'apply', '--3way', join('..', '..', 'pin-bump.patch'))
            } catch {
              core.setFailed([
                `Failed to apply ci/pinned.json bump commit ${pin_bump_sha}.`,
@@ -122,5 +130,7 @@ runs:
                `Please rebase the PR or ensure the pin bump is standalone.`
              ].join(' '))
              return
            } finally {
              await rm('pin-bump.patch')
            }
          }
+1 −1
Original line number Diff line number Diff line
@@ -26,7 +26,7 @@
  - all:
      - changed-files:
          - any-glob-to-any-file:
              - .github/actions/*
              - .github/actions/**/*
              - .github/workflows/*
              - .github/labeler*.yml
              - ci/**/*.*
+2 −0
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@

- [reaction](https://reaction.ppom.me/), a daemon that scans program outputs for repeated patterns, and takes action. A common usage is to scan ssh and webserver logs, and to ban hosts that cause multiple authentication errors. A modern alternative to fail2ban. Available as [services.reaction](#opt-services.reaction.enable).

- [Tailscale Serve](https://tailscale.com/kb/1552/tailscale-services), configure Tailscale Serve for exposing local services to your tailnet. Available as [services.tailscale.serve](#opt-services.tailscale.serve.enable).

- [qui](https://github.com/autobrr/qui), a modern alternative webUI for qBittorrent, with multi-instance support. Written in Go/React. Available as [services.qui](#opt-services.qui.enable).

- [LibreChat](https://www.librechat.ai/), open-source self-hostable ChatGPT clone with Agents and RAG APIs. Available as [services.librechat](#opt-services.librechat.enable).
+1 −0
Original line number Diff line number Diff line
@@ -1391,6 +1391,7 @@
  ./services/networking/syncthing.nix
  ./services/networking/tailscale-auth.nix
  ./services/networking/tailscale-derper.nix
  ./services/networking/tailscale-serve.nix
  ./services/networking/tailscale.nix
  ./services/networking/tayga.nix
  ./services/networking/tcpcrypt.nix
+145 −0
Original line number Diff line number Diff line
{
  config,
  lib,
  pkgs,
  ...
}:

let
  cfg = config.services.tailscale.serve;
  settingsFormat = pkgs.formats.json { };

  # Build the serve config structure with svc: prefix on service names
  serveConfig = {
    version = "0.0.1";
    services = lib.mapAttrs' (
      name: serviceCfg:
      lib.nameValuePair "svc:${name}" (
        {
          endpoints = serviceCfg.endpoints;
        }
        // lib.optionalAttrs (serviceCfg.advertised != null) {
          inherit (serviceCfg) advertised;
        }
      )
    ) cfg.services;
  };

  configFile =
    if cfg.configFile != null then
      cfg.configFile
    else
      settingsFormat.generate "tailscale-serve-config.json" serveConfig;
in
{
  meta.maintainers = with lib.maintainers; [
    bouk
  ];

  options.services.tailscale.serve = {
    enable = lib.mkEnableOption "Tailscale Serve configuration";

    configFile = lib.mkOption {
      type = lib.types.nullOr lib.types.path;
      default = null;
      description = ''
        Path to a Tailscale Serve configuration file in JSON format.
        If set, this takes precedence over {option}`services.tailscale.serve.services`.

        See <https://tailscale.com/kb/1589/tailscale-services-configuration-file> for the configuration format.
      '';
      example = "/run/secrets/tailscale-serve.json";
    };

    services = lib.mkOption {
      type = lib.types.attrsOf (
        lib.types.submodule {
          options = {
            endpoints = lib.mkOption {
              type = lib.types.attrsOf lib.types.str;
              description = ''
                Map of incoming traffic patterns to local targets.

                Keys should be in the format `<protocol>:<port>` or `<protocol>:<port-range>`.
                Currently only `tcp` protocol is supported.

                Values should be in the format `<protocol>://<host:port>` where protocol
                is `http`, `https`, or `tcp`.
              '';
              example = {
                "tcp:443" = "https://localhost:443";
                "tcp:8080" = "http://localhost:8080";
              };
            };

            advertised = lib.mkOption {
              type = lib.types.nullOr lib.types.bool;
              default = null;
              description = ''
                Whether the service should accept new connections.
                Defaults to `true` when not specified.
              '';
            };
          };
        }
      );
      default = { };
      description = ''
        Services to configure for Tailscale Serve.

        Each attribute name should be the service name (without the `svc:` prefix).
        The `svc:` prefix will be added automatically.

        See <https://tailscale.com/kb/1589/tailscale-services-configuration-file> for details.
      '';
      example = lib.literalExpression ''
        {
          web-server = {
            endpoints = {
              "tcp:443" = "https://localhost:443";
            };
          };
          api = {
            endpoints = {
              "tcp:8080" = "http://localhost:8080";
            };
            advertised = true;
          };
        }
      '';
    };
  };

  config = lib.mkIf cfg.enable {
    assertions = [
      {
        assertion = config.services.tailscale.enable;
        message = "services.tailscale.serve requires services.tailscale.enable to be true";
      }
      {
        assertion = cfg.configFile != null || cfg.services != { };
        message = "services.tailscale.serve requires either configFile or services to be set";
      }
    ];

    systemd.services.tailscale-serve = {
      description = "Tailscale Serve Configuration";

      after = [
        "tailscaled.service"
        "tailscaled-autoconnect.service"
        "tailscaled-set.service"
      ];
      wants = [ "tailscaled.service" ];
      wantedBy = [ "multi-user.target" ];

      restartTriggers = [ configFile ];

      serviceConfig = {
        Type = "oneshot";
        RemainAfterExit = true;
        ExecStart = "${lib.getExe config.services.tailscale.package} serve set-config --all ${configFile}";
      };
    };
  };
}
Loading