Unverified Commit 98430f95 authored by Arne Keller's avatar Arne Keller Committed by GitHub
Browse files

pinchflat: init at 2025.3.17, nixos/pinchflat: init (#364135)

parents 02045a9c 3e3b7747
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -4188,6 +4188,12 @@
    githubId = 1774239;
    name = "Charlie Egan";
  };
  charludo = {
    email = "github@charlotteharludo.com";
    github = "charludo";
    githubId = 47758554;
    name = "Charlotte Harludo";
  };
  chayleaf = {
    email = "chayleaf-nix@pavluk.org";
    github = "chayleaf";
+2 −0
Original line number Diff line number Diff line
@@ -116,6 +116,8 @@

- [zwave-js-ui](https://zwave-js.github.io/zwave-js-ui/), a full featured Z-Wave Control Panel and MQTT Gateway. Available as [services.zwave-js-ui](#opt-services.zwave-js-ui.enable).

- [Pinchflat](https://github.com/kieraneglin/pinchflat), a selfhosted YouTube media manager used to track channels and download videos on release. Available as [services.pinchflat](#opt-services.pinchflat.enable).

- [Amazon CloudWatch Agent](https://github.com/aws/amazon-cloudwatch-agent), the official telemetry collector for AWS CloudWatch and AWS X-Ray. Available as [services.amazon-cloudwatch-agent](options.html#opt-services.amazon-cloudwatch-agent.enable).

- [Fluent Bit](https://github.com/fluent/fluent-bit), a fast Log, Metrics and Traces Processor and Forwarder. Available as [services.fluent-bit](#opt-services.fluent-bit.enable).
+1 −0
Original line number Diff line number Diff line
@@ -859,6 +859,7 @@
  ./services/misc/parsoid.nix
  ./services/misc/persistent-evdev.nix
  ./services/misc/pghero.nix
  ./services/misc/pinchflat.nix
  ./services/misc/pinnwand.nix
  ./services/misc/plex.nix
  ./services/misc/plikd.nix
+158 −0
Original line number Diff line number Diff line
{
  config,
  pkgs,
  lib,
  ...
}:

let
  cfg = config.services.pinchflat;
  inherit (lib)
    mkEnableOption
    mkPackageOption
    mkOption
    types
    mkIf
    getExe
    literalExpression
    optional
    attrValues
    mapAttrs
    ;

  stateDir = "/var/lib/pinchflat";
in
{
  options = {
    services.pinchflat = {
      enable = mkEnableOption "pinchflat";

      mediaDir = mkOption {
        type = types.path;
        default = "${stateDir}/media";
        description = "The directory into which Pinchflat downloads videos.";
      };

      port = mkOption {
        type = types.port;
        default = 8945;
        description = "Port on which the Pinchflat web interface is available.";
      };

      openFirewall = mkOption {
        type = types.bool;
        default = false;
        description = "Open ports in the firewall for the Pinchflat web interface";
      };

      selfhosted = mkOption {
        type = types.bool;
        default = false;
        description = "Use a weak secret. If true, you are not required to provide a {env}`SECRET_KEY_BASE` through the `secretsFile` option. Do not use this option in production!";
      };

      logLevel = mkOption {
        type = types.enum [
          "debug"
          "info"
          "warning"
          "error"
        ];
        default = "info";
        description = "Log level for Pinchflat.";
      };

      extraConfig = mkOption {
        type =
          with types;
          attrsOf (
            nullOr (oneOf [
              bool
              int
              str
            ])
          );
        default = { };
        example = literalExpression ''
          {
            YT_DLP_WORKER_CONCURRENCY = 1;
          }
        '';
        description = ''
          The configuration of Pinchflat is handled through environment variables.
          The available configuration options can be found in [the Pinchflat README](https://github.com/kieraneglin/pinchflat/README.md#environment-variables).
        '';
      };

      secretsFile = mkOption {
        type = with types; nullOr path;
        default = null;
        example = "/run/secrets/pinchflat";
        description = ''
          Secrets like {env}`SECRET_KEY_BASE` and {env}`BASIC_AUTH_PASSWORD`
          should be passed to the service without adding them to the world-readable Nix store.

          Note that either this file needs to be available on the host on which `pinchflat` is running,
          or the option `selfhosted` must be `true`.
          Further, {env}`SECRET_KEY_BASE` has a minimum length requirement of 64 bytes.
          One way to generate such a secret is to use `openssl rand -hex 64`.

          As an example, the contents of the file might look like this:
          ```
          SECRET_KEY_BASE=...copy-paste a secret token here...
          BASIC_AUTH_USERNAME=...basic auth username...
          BASIC_AUTH_PASSWORD=...basic auth password...
          ```
        '';
      };

      package = mkPackageOption pkgs "pinchflat" { };
    };
  };

  config = mkIf cfg.enable {
    assertions = [
      {
        assertion = cfg.selfhosted || !builtins.isNull cfg.secretsFile;
        message = "Either `selfhosted` must be true, or a `secretsFile` must be configured.";
      }
    ];

    systemd.services.pinchflat = {
      description = "pinchflat";
      after = [ "network.target" ];
      wantedBy = [ "multi-user.target" ];

      serviceConfig = {
        Type = "simple";
        DynamicUser = true;
        StateDirectory = baseNameOf stateDir;
        Environment =
          [
            "PORT=${builtins.toString cfg.port}"
            "TZ=${config.time.timeZone}"
            "MEDIA_PATH=${cfg.mediaDir}"
            "CONFIG_PATH=${stateDir}"
            "DATABASE_PATH=${stateDir}/db/pinchflat.db"
            "LOG_PATH=${stateDir}/logs/pinchflat.log"
            "METADATA_PATH=${stateDir}/metadata"
            "EXTRAS_PATH=${stateDir}/extras"
            "TMPFILE_PATH=${stateDir}/tmp"
            "TZ_DATA_PATH=${stateDir}/extras/elixir_tz_data"
            "LOG_LEVEL=${cfg.logLevel}"
            "PHX_SERVER=true"
          ]
          ++ optional cfg.selfhosted [ "RUN_CONTEXT=selfhosted" ]
          ++ attrValues (mapAttrs (name: value: name + "=" + builtins.toString value) cfg.extraConfig);
        EnvironmentFile = optional (cfg.secretsFile != null) cfg.secretsFile;
        ExecStartPre = "${lib.getExe' cfg.package "migrate"}";
        ExecStart = "${getExe cfg.package} start";
        Restart = "on-failure";
      };
    };

    networking.firewall = mkIf cfg.openFirewall {
      allowedTCPPorts = [ cfg.port ];
    };
  };
}
+1073 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading