nix: format all nix files with nixfmt

This commit is contained in:
Tom van Dijk 2025-07-28 12:42:47 +02:00
parent e278316615
commit 4895579c72
No known key found for this signature in database
GPG key ID: 7A984C8207ADBA51
3 changed files with 274 additions and 234 deletions

View file

@ -4,28 +4,31 @@
lib, lib,
... ...
}: }:
with lib; let with lib;
mkKeyValue = key: value: let
if value == true mkKeyValue =
then key: value:
if value == true then
# sets with a true boolean value are coerced to just the key name # sets with a true boolean value are coerced to just the key name
key key
else if value == false else if value == false then
then
# or omitted completely when false # or omitted completely when false
"" ""
else (generators.mkKeyValueDefault {inherit mkValueString;} ": " key value); else
(generators.mkKeyValueDefault { inherit mkValueString; } ": " key value);
mkAttrsString = value: (generators.toKeyValue {inherit mkKeyValue;} value); mkAttrsString = value: (generators.toKeyValue { inherit mkKeyValue; } value);
mkValueString = value: mkValueString =
if isList value value:
then (concatStringsSep ", " (map mkValueString value)) if isList value then
else if isAttrs value (concatStringsSep ", " (map mkValueString value))
then "\n" + (mkAttrsString value) else if isAttrs value then
else (generators.mkValueStringDefault {} value); "\n" + (mkAttrsString value)
else
(generators.mkValueStringDefault { } value);
mkSectionName = value: "[" + (escape ["[" "]"] value) + "]"; mkSectionName = value: "[" + (escape [ "[" "]" ] value) + "]";
mkSection = name: attrs: '' mkSection = name: attrs: ''
${mkSectionName name} ${mkSectionName name}
@ -57,7 +60,8 @@ with lib; let
externalCacheDir = "/var/cache/copyparty"; externalCacheDir = "/var/cache/copyparty";
externalStateDir = "/var/lib/copyparty"; externalStateDir = "/var/lib/copyparty";
defaultShareDir = "${externalStateDir}/data"; defaultShareDir = "${externalStateDir}/data";
in { in
{
options.services.copyparty = { options.services.copyparty = {
enable = mkEnableOption "web-based file manager"; enable = mkEnableOption "web-based file manager";
@ -128,7 +132,10 @@ in {
}; };
accounts = mkOption { accounts = mkOption {
type = types.attrsOf (types.submodule ({...}: { type = types.attrsOf (
types.submodule (
{ ... }:
{
options = { options = {
passwordFile = mkOption { passwordFile = mkOption {
type = types.str; type = types.str;
@ -139,11 +146,13 @@ in {
example = "/run/keys/copyparty/ed"; example = "/run/keys/copyparty/ed";
}; };
}; };
})); }
)
);
description = '' description = ''
A set of copyparty accounts to create. A set of copyparty accounts to create.
''; '';
default = {}; default = { };
example = literalExpression '' example = literalExpression ''
{ {
ed.passwordFile = "/run/keys/copyparty/ed"; ed.passwordFile = "/run/keys/copyparty/ed";
@ -152,7 +161,10 @@ in {
}; };
volumes = mkOption { volumes = mkOption {
type = types.attrsOf (types.submodule ({...}: { type = types.attrsOf (
types.submodule (
{ ... }:
{
options = { options = {
path = mkOption { path = mkOption {
type = types.path; type = types.path;
@ -211,15 +223,19 @@ in {
nohash = "\.iso$"; nohash = "\.iso$";
}; };
''; '';
default = {}; default = { };
}; };
}; };
})); }
)
);
description = "A set of copyparty volumes to create"; description = "A set of copyparty volumes to create";
default = { default = {
"/" = { "/" = {
path = defaultShareDir; path = defaultShareDir;
access = {r = "*";}; access = {
r = "*";
};
}; };
}; };
example = literalExpression '' example = literalExpression ''
@ -238,27 +254,30 @@ in {
}; };
}; };
config = mkIf cfg.enable (let config = mkIf cfg.enable (
let
command = "${getExe cfg.package} -c ${runtimeConfigPath}"; command = "${getExe cfg.package} -c ${runtimeConfigPath}";
in { in
{
systemd.services.copyparty = { systemd.services.copyparty = {
description = "http file sharing hub"; description = "http file sharing hub";
wantedBy = ["multi-user.target"]; wantedBy = [ "multi-user.target" ];
environment = { environment = {
PYTHONUNBUFFERED = "true"; PYTHONUNBUFFERED = "true";
XDG_CONFIG_HOME = externalStateDir; XDG_CONFIG_HOME = externalStateDir;
}; };
preStart = let preStart =
replaceSecretCommand = name: attrs: "${getExe pkgs.replace-secret} '${ let
passwordPlaceholder name replaceSecretCommand =
}' '${attrs.passwordFile}' ${runtimeConfigPath}"; name: attrs:
in '' "${getExe pkgs.replace-secret} '${passwordPlaceholder name}' '${attrs.passwordFile}' ${runtimeConfigPath}";
in
''
set -euo pipefail set -euo pipefail
install -m 600 ${configFile} ${runtimeConfigPath} install -m 600 ${configFile} ${runtimeConfigPath}
${concatStringsSep "\n" ${concatStringsSep "\n" (mapAttrsToList replaceSecretCommand cfg.accounts)}
(mapAttrsToList replaceSecretCommand cfg.accounts)}
''; '';
serviceConfig = { serviceConfig = {
@ -267,29 +286,23 @@ in {
# Hardening options # Hardening options
User = cfg.user; User = cfg.user;
Group = cfg.group; Group = cfg.group;
RuntimeDirectory = ["copyparty"]; RuntimeDirectory = [ "copyparty" ];
RuntimeDirectoryMode = "0700"; RuntimeDirectoryMode = "0700";
StateDirectory = ["copyparty"]; StateDirectory = [ "copyparty" ];
StateDirectoryMode = "0700"; StateDirectoryMode = "0700";
CacheDirectory = lib.mkIf (cfg.settings ? hist) ["copyparty"]; CacheDirectory = lib.mkIf (cfg.settings ? hist) [ "copyparty" ];
CacheDirectoryMode = lib.mkIf (cfg.settings ? hist) "0700"; CacheDirectoryMode = lib.mkIf (cfg.settings ? hist) "0700";
WorkingDirectory = externalStateDir; WorkingDirectory = externalStateDir;
BindReadOnlyPaths = BindReadOnlyPaths = [
[
"/nix/store" "/nix/store"
"-/etc/resolv.conf" "-/etc/resolv.conf"
"-/etc/nsswitch.conf" "-/etc/nsswitch.conf"
"-/etc/hosts" "-/etc/hosts"
"-/etc/localtime" "-/etc/localtime"
] ] ++ (mapAttrsToList (k: v: "-${v.passwordFile}") cfg.accounts);
++ (mapAttrsToList (k: v: "-${v.passwordFile}") cfg.accounts);
BindPaths = BindPaths =
( (if cfg.settings ? hist then [ cfg.settings.hist ] else [ ])
if cfg.settings ? hist ++ [ externalStateDir ]
then [cfg.settings.hist]
else []
)
++ [externalStateDir]
++ (mapAttrsToList (k: v: v.path) cfg.volumes); ++ (mapAttrsToList (k: v: v.path) cfg.volumes);
# ProtectSystem = "strict"; # ProtectSystem = "strict";
# Note that unlike what 'ro' implies, # Note that unlike what 'ro' implies,
@ -332,11 +345,10 @@ in {
mode = ":755"; mode = ":755";
}; };
} }
) ) cfg.volumes
cfg.volumes
); );
users.groups.copyparty = lib.mkIf (cfg.user == "copyparty" && cfg.group == "copyparty") {}; users.groups.copyparty = lib.mkIf (cfg.user == "copyparty" && cfg.group == "copyparty") { };
users.users.copyparty = lib.mkIf (cfg.user == "copyparty" && cfg.group == "copyparty") { users.users.copyparty = lib.mkIf (cfg.user == "copyparty" && cfg.group == "copyparty") {
description = "Service user for copyparty"; description = "Service user for copyparty";
group = "copyparty"; group = "copyparty";
@ -344,9 +356,7 @@ in {
isSystemUser = true; isSystemUser = true;
}; };
environment.systemPackages = lib.mkIf cfg.mkHashWrapper [ environment.systemPackages = lib.mkIf cfg.mkHashWrapper [
(pkgs.writeShellScriptBin (pkgs.writeShellScriptBin "copyparty-hash" ''
"copyparty-hash"
''
set -a # automatically export variables set -a # automatically export variables
# set same environment variables as the systemd service # set same environment variables as the systemd service
${lib.pipe config.systemd.services.copyparty.environment [ ${lib.pipe config.systemd.services.copyparty.environment [
@ -359,5 +369,6 @@ in {
exec ${command} --ah-cli exec ${command} --ah-cli
'') '')
]; ];
}); }
);
} }

View file

@ -1,49 +1,67 @@
{ lib, stdenv, makeWrapper, fetchurl, util-linux, python, jinja2, impacket, pyftpdlib, pyopenssl, argon2-cffi, pillow, pyvips, pyzmq, ffmpeg, mutagen, {
lib,
stdenv,
makeWrapper,
fetchurl,
util-linux,
python,
jinja2,
impacket,
pyftpdlib,
pyopenssl,
argon2-cffi,
pillow,
pyvips,
pyzmq,
ffmpeg,
mutagen,
# use argon2id-hashed passwords in config files (sha2 is always available) # use argon2id-hashed passwords in config files (sha2 is always available)
withHashedPasswords ? true, withHashedPasswords ? true,
# generate TLS certificates on startup (pointless when reverse-proxied) # generate TLS certificates on startup (pointless when reverse-proxied)
withCertgen ? false, withCertgen ? false,
# create thumbnails with Pillow; faster than FFmpeg / MediaProcessing # create thumbnails with Pillow; faster than FFmpeg / MediaProcessing
withThumbnails ? true, withThumbnails ? true,
# create thumbnails with PyVIPS; even faster, uses more memory # create thumbnails with PyVIPS; even faster, uses more memory
# -- can be combined with Pillow to support more filetypes # -- can be combined with Pillow to support more filetypes
withFastThumbnails ? false, withFastThumbnails ? false,
# enable FFmpeg; thumbnails for most filetypes (also video and audio), extract audio metadata, transcode audio to opus # enable FFmpeg; thumbnails for most filetypes (also video and audio), extract audio metadata, transcode audio to opus
# -- possibly dangerous if you allow anonymous uploads, since FFmpeg has a huge attack surface # -- possibly dangerous if you allow anonymous uploads, since FFmpeg has a huge attack surface
# -- can be combined with Thumbnails and/or FastThumbnails, since FFmpeg is slower than both # -- can be combined with Thumbnails and/or FastThumbnails, since FFmpeg is slower than both
withMediaProcessing ? true, withMediaProcessing ? true,
# if MediaProcessing is not enabled, you probably want this instead (less accurate, but much safer and faster) # if MediaProcessing is not enabled, you probably want this instead (less accurate, but much safer and faster)
withBasicAudioMetadata ? false, withBasicAudioMetadata ? false,
# send ZeroMQ messages from event-hooks # send ZeroMQ messages from event-hooks
withZeroMQ ? true, withZeroMQ ? true,
# enable FTPS support in the FTP server # enable FTPS support in the FTP server
withFTPS ? false, withFTPS ? false,
# samba/cifs server; dangerous and buggy, enable if you really need it # samba/cifs server; dangerous and buggy, enable if you really need it
withSMB ? false, withSMB ? false,
# extra packages to add to the PATH # extra packages to add to the PATH
extraPackages ? [ ], extraPackages ? [ ],
# function that accepts a python packageset and returns a list of packages to # function that accepts a python packageset and returns a list of packages to
# be added to the python venv. useful for scripts and such that require # be added to the python venv. useful for scripts and such that require
# additional dependencies # additional dependencies
extraPythonPackages ? (_p: [ ]), extraPythonPackages ? (_p: [ ]),
}: }:
let let
pinData = lib.importJSON ./pin.json; pinData = lib.importJSON ./pin.json;
pyEnv = python.withPackages (ps: pyEnv = python.withPackages (
with ps; [ ps:
with ps;
[
jinja2 jinja2
] ]
++ lib.optional withSMB impacket ++ lib.optional withSMB impacket
@ -57,7 +75,8 @@ let
++ lib.optional withZeroMQ pyzmq ++ lib.optional withZeroMQ pyzmq
++ (extraPythonPackages ps) ++ (extraPythonPackages ps)
); );
in stdenv.mkDerivation { in
stdenv.mkDerivation {
pname = "copyparty"; pname = "copyparty";
version = pinData.version; version = pinData.version;
src = fetchurl { src = fetchurl {
@ -70,7 +89,9 @@ in stdenv.mkDerivation {
installPhase = '' installPhase = ''
install -Dm755 $src $out/share/copyparty-sfx.py install -Dm755 $src $out/share/copyparty-sfx.py
makeWrapper ${pyEnv.interpreter} $out/bin/copyparty \ makeWrapper ${pyEnv.interpreter} $out/bin/copyparty \
--set PATH '${lib.makeBinPath ([ util-linux ] ++ extraPackages ++ lib.optional withMediaProcessing ffmpeg)}:$PATH' \ --set PATH '${
lib.makeBinPath ([ util-linux ] ++ extraPackages ++ lib.optional withMediaProcessing ffmpeg)
}:$PATH' \
--add-flags "$out/share/copyparty-sfx.py" --add-flags "$out/share/copyparty-sfx.py"
''; '';
meta.mainProgram = "copyparty"; meta.mainProgram = "copyparty";

View file

@ -4,16 +4,22 @@
flake-utils.url = "github:numtide/flake-utils"; flake-utils.url = "github:numtide/flake-utils";
}; };
outputs = { self, nixpkgs, flake-utils }: outputs =
{
self,
nixpkgs,
flake-utils,
}:
{ {
nixosModules.default = ./contrib/nixos/modules/copyparty.nix; nixosModules.default = ./contrib/nixos/modules/copyparty.nix;
overlays.default = self: super: { overlays.default = self: super: {
copyparty = copyparty = self.python3.pkgs.callPackage ./contrib/package/nix/copyparty {
self.python3.pkgs.callPackage ./contrib/package/nix/copyparty {
ffmpeg = self.ffmpeg-full; ffmpeg = self.ffmpeg-full;
}; };
}; };
} // flake-utils.lib.eachDefaultSystem (system: }
// flake-utils.lib.eachDefaultSystem (
system:
let let
pkgs = import nixpkgs { pkgs = import nixpkgs {
inherit system; inherit system;
@ -22,10 +28,12 @@
}; };
overlays = [ self.overlays.default ]; overlays = [ self.overlays.default ];
}; };
in { in
{
packages = { packages = {
inherit (pkgs) copyparty; inherit (pkgs) copyparty;
default = self.packages.${system}.copyparty; default = self.packages.${system}.copyparty;
}; };
}); }
);
} }