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

This commit is contained in:
Arne Keller
2025-03-26 11:06:02 +01:00
committed by GitHub
6 changed files with 1315 additions and 0 deletions
+6
View File
@@ -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";
@@ -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
View File
@@ -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
View File
@@ -0,0 +1,158 @@
{
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 ];
};
};
}
File diff suppressed because it is too large Load Diff
+75
View File
@@ -0,0 +1,75 @@
{
lib,
fetchFromGitHub,
fetchYarnDeps,
beamPackages,
yarn,
nodejs,
esbuild,
tailwindcss,
fixup-yarn-lock,
apprise,
yt-dlp,
}:
beamPackages.mixRelease rec {
pname = "pinchflat";
version = "2025.3.17";
src = fetchFromGitHub {
owner = "kieraneglin";
repo = "pinchflat";
rev = "v${version}";
hash = "sha256-XHYCYC3SEVyheBV6diE2pn1AJARml+aNNUjJw2tVKTk=";
};
mixNixDeps = import ./mix.nix {
inherit beamPackages lib;
};
removeCookie = false;
yarnOfflineCache = fetchYarnDeps {
yarnLock = "${src}/assets/yarn.lock";
sha256 = "sha256-xJL+qcohtu+OmZ31E1QU9uqBWAFGejKIO3XRd+R6z/4=";
};
nativeBuildInputs = [
fixup-yarn-lock
tailwindcss
yarn
];
buildInputs = [ nodejs ];
postBuild = ''
export HOME=$PWD
fixup-yarn-lock ~/assets/yarn.lock
yarn --cwd assets config --offline set yarn-offline-mirror $yarnOfflineCache
yarn --cwd assets install --offline --frozen-lockfile --ignore-engines --ignore-scripts --no-progress
patchShebangs ~/assets/node_modules
# phoenixframework expects platform-specific tailwind/esbuild binaries in a specific location:
# https://github.com/phoenixframework/tailwind/blob/194ab0f979782e4ccf2fe796042bf8e20967df93/lib/tailwind.ex#L243-L251
targets="linux-x64 linux-arm64 macos-x64 macos-arm64"
for target in $targets; do
ln -s "${tailwindcss}/bin/tailwindcss" "_build/tailwind-$target"
ln -s "${esbuild}/bin/esbuild" "_build/esbuild-$target"
done
mix do deps.loadpaths --no-deps-check, tailwind default --minify + esbuild default --minify + phx.digest
'';
postInstall = ''
wrapProgram $out/bin/pinchflat --prefix PATH : ${
lib.makeBinPath [
apprise
yt-dlp
]
}
'';
meta = {
description = "Your next YouTube media manager";
homepage = "https://github.com/kieraneglin/pinchflat";
license = lib.licenses.agpl3Only;
maintainers = with lib.maintainers; [ charludo ];
platforms = lib.platforms.unix;
mainProgram = "pinchflat";
};
}