diff --git a/hosts/fw/modules/pyload.nix b/hosts/fw/modules/pyload.nix index ed3be4e..bef2291 100644 --- a/hosts/fw/modules/pyload.nix +++ b/hosts/fw/modules/pyload.nix @@ -3,27 +3,42 @@ let cids = import ./staticids.nix; networkPrefix = config.networkPrefix; - user = { + pyloadUser = { isSystemUser = true; uid = cids.uids.pyload; group = "pyload"; home = "/var/lib/pyload"; createHome = true; }; - group = { + pyloadGroup = { gid = cids.gids.pyload; }; + + jellyfinUser = { + isSystemUser = true; + uid = cids.uids.jellyfin; + group = "jellyfin"; + home = "/var/lib/jellyfin"; + createHome = true; + }; + jellyfinGroup = { + gid = cids.gids.jellyfin; + }; in { - users.users.pyload = user; - users.groups.pyload = group; + users.users.pyload = pyloadUser; + users.groups.pyload = pyloadGroup; + users.users.jellyfin = jellyfinUser; + users.groups.jellyfin = jellyfinGroup; # Create the multimedia directory structure on the host systemd.tmpfiles.rules = [ "d /var/lib/multimedia 0755 root root - -" "d /var/lib/multimedia/downloads 0755 pyload pyload - -" - "d /var/lib/multimedia/movies 0755 pyload pyload - -" - "d /var/lib/multimedia/tv-shows 0755 pyload pyload - -" + "d /var/lib/multimedia/movies 0755 jellyfin jellyfin - -" + "d /var/lib/multimedia/tv-shows 0755 jellyfin jellyfin - -" + "d /var/lib/multimedia/music 0755 jellyfin jellyfin - -" + "d /var/lib/jellyfin 0755 jellyfin jellyfin - -" ]; containers.pyload = { @@ -39,6 +54,10 @@ in hostPath = "/var/lib/pyload"; isReadOnly = false; }; + "/var/lib/jellyfin" = { + hostPath = "/var/lib/jellyfin"; + isReadOnly = false; + }; "/multimedia" = { hostPath = "/var/lib/multimedia"; isReadOnly = false; @@ -46,6 +65,19 @@ in }; config = { lib, config, pkgs, ... }: { + nixpkgs.overlays = [ + (import ../utils/overlays/packages.nix) + ]; + + + nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [ + "unrar" + ]; + + environment.systemPackages = with pkgs; [ + unrar # Required for RAR archive extraction + ]; + networking = { hostName = "pyload"; useHostResolvConf = false; @@ -64,8 +96,35 @@ in port = 8000; }; - users.users.pyload = user; - users.groups.pyload = group; + services.jellyfin = { + enable = true; + openFirewall = true; + }; + + # Disable SSL certificate verification + systemd.services.pyload = { + environment = { + PYLOAD__GENERAL__SSL_VERIFY = "0"; + }; + + # Bind-mount DNS configuration files and system tools into the chroot + serviceConfig = { + BindReadOnlyPaths = [ + "/etc/resolv.conf" + "/etc/nsswitch.conf" + "/etc/hosts" + "/etc/ssl" + "/etc/static/ssl" + # Make all system packages (including unrar) accessible + "/run/current-system/sw/bin" + ]; + }; + }; + + users.users.pyload = pyloadUser; + users.groups.pyload = pyloadGroup; + users.users.jellyfin = jellyfinUser; + users.groups.jellyfin = jellyfinGroup; system.stateVersion = "24.05"; }; diff --git a/scripts/update-pyload-hash b/scripts/update-pyload-hash new file mode 100755 index 0000000..100ee8b --- /dev/null +++ b/scripts/update-pyload-hash @@ -0,0 +1,106 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Script directory +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" + +# Check if commit SHA is provided +if [ $# -ne 1 ]; then + echo -e "${RED}Error: Git commit SHA required${NC}" + echo "Usage: $0 " + echo "Example: $0 e5fe7038f3e116d878c58059323b682e426f9c84" + echo "" + echo "To find the latest commit:" + echo " Visit: https://github.com/pyload/pyload/commits/main" + exit 1 +fi + +COMMIT_SHA="$1" + +# Validate commit SHA format (40 character hex string) +if ! [[ "$COMMIT_SHA" =~ ^[0-9a-f]{40}$ ]]; then + echo -e "${RED}Error: Invalid commit SHA format${NC}" + echo "Commit SHA must be a 40-character hexadecimal string" + exit 1 +fi + +echo -e "${GREEN}==> Updating pyload-ng to commit: ${COMMIT_SHA}${NC}" + +# File to update +PKG_FILE="$REPO_ROOT/utils/pkgs/pyload-ng-updated.nix" + +if [ ! -f "$PKG_FILE" ]; then + echo -e "${RED}Error: Package file not found: $PKG_FILE${NC}" + exit 1 +fi + +# Step 1: Update commit SHA in package file +echo -e "${YELLOW}Step 1: Updating commit SHA in package file...${NC}" +sed -i "s/rev = \"[0-9a-f]*\";/rev = \"$COMMIT_SHA\";/" "$PKG_FILE" +echo " ✓ Updated commit SHA in $PKG_FILE" + +# Step 2: Set hash to a fake value to trigger hash discovery +echo -e "${YELLOW}Step 2: Setting hash to fake value...${NC}" +sed -i 's/hash = "sha256-[^"]*";/hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";/' "$PKG_FILE" +echo " ✓ Updated hash in $PKG_FILE" + +# Step 3: Build package to discover the correct hash +echo -e "${YELLOW}Step 3: Building package to discover hash...${NC}" +BUILD_OUTPUT=$(nix-build --impure -E "with import { overlays = [ (import $REPO_ROOT/utils/overlays/packages.nix) ]; }; callPackage $PKG_FILE { }" 2>&1 || true) + +# Extract hash from error message +HASH=$(echo "$BUILD_OUTPUT" | grep -oP '\s+got:\s+\Ksha256-[A-Za-z0-9+/=]+' | head -1) + +if [ -z "$HASH" ]; then + echo -e "${RED}Error: Failed to extract hash from build output${NC}" + echo "Build output:" + echo "$BUILD_OUTPUT" + exit 1 +fi + +echo " ✓ Discovered hash: $HASH" + +# Step 4: Update package file with the correct hash +echo -e "${YELLOW}Step 4: Updating hash in package file...${NC}" +sed -i "s|hash = \"sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\";|hash = \"$HASH\";|" "$PKG_FILE" +echo " ✓ Updated hash in $PKG_FILE" + +# Step 5: Verify the build succeeds +echo -e "${YELLOW}Step 5: Verifying build with correct hash...${NC}" +if nix-build --impure -E "with import { overlays = [ (import $REPO_ROOT/utils/overlays/packages.nix) ]; }; callPackage $PKG_FILE { }" > /dev/null 2>&1; then + echo " ✓ Build verification successful" +else + echo -e "${RED}Error: Build verification failed${NC}" + exit 1 +fi + +# Step 6: Test configuration for fw host (which uses pyload) +echo -e "${YELLOW}Step 6: Testing fw configuration...${NC}" +cd "$REPO_ROOT" +if ./scripts/test-configuration fw > /dev/null 2>&1; then + echo " ✓ Configuration test passed" +else + echo -e "${RED}Warning: Configuration test failed${NC}" + echo "This may be due to missing secrets or other issues unrelated to the hash update." +fi + +# Success summary +echo -e "${GREEN}" +echo "======================================" +echo "✓ pyload-ng updated successfully!" +echo "======================================" +echo "Commit: $COMMIT_SHA" +echo "Hash: $HASH" +echo -e "${NC}" +echo "Next steps:" +echo " 1. Review changes: git diff $PKG_FILE" +echo " 2. Test locally if needed" +echo " 3. Commit changes: git add $PKG_FILE && git commit -m 'update: pyload-ng to commit ${COMMIT_SHA:0:8}'" +echo " 4. Push to trigger automatic deployment" diff --git a/utils/overlays/packages.nix b/utils/overlays/packages.nix index cffe405..811ae3b 100644 --- a/utils/overlays/packages.nix +++ b/utils/overlays/packages.nix @@ -6,5 +6,15 @@ self: super: { openmanus = (super.callPackage ../pkgs/openmanus.nix { }); ai-mailer = self.callPackage ../pkgs/ai-mailer.nix { }; + # Python packages + python3 = super.python3.override { + packageOverrides = pself: psuper: { + mini-racer = pself.callPackage ../pkgs/mini-racer.nix { }; + }; + }; + python3Packages = self.python3.pkgs; + + pyload-ng = self.callPackage ../pkgs/pyload-ng-updated.nix { pyload-ng = super.pyload-ng; }; + # vscode-insiders = (super.callPackage ../pkgs/vscode-insiders.nix { }); } diff --git a/utils/pkgs/mini-racer.nix b/utils/pkgs/mini-racer.nix new file mode 100644 index 0000000..3d00cc1 --- /dev/null +++ b/utils/pkgs/mini-racer.nix @@ -0,0 +1,41 @@ +{ lib +, buildPythonPackage +, fetchPypi +, stdenv +, autoPatchelfHook +}: + +buildPythonPackage rec { + pname = "mini-racer"; + version = "0.12.4"; + format = "wheel"; + + src = fetchPypi { + pname = "mini_racer"; + inherit version format; + dist = "py3"; + python = "py3"; + abi = "none"; + platform = "manylinux_2_31_x86_64"; + hash = "sha256-aaHETQKpBpuIFoTO8VotdH/gdD3ynq3Igf2nACquX9I="; + }; + + nativeBuildInputs = [ + autoPatchelfHook + ]; + + buildInputs = [ + stdenv.cc.cc.lib + ]; + + # Don't strip binaries, it breaks V8 + dontStrip = true; + + meta = with lib; { + description = "Minimal Python wrapper for V8 JavaScript engine"; + homepage = "https://github.com/bpcreech/PyMiniRacer"; + license = licenses.isc; + maintainers = [ ]; + platforms = [ "x86_64-linux" ]; + }; +} diff --git a/utils/pkgs/pyload-ng-updated.nix b/utils/pkgs/pyload-ng-updated.nix new file mode 100644 index 0000000..195eebf --- /dev/null +++ b/utils/pkgs/pyload-ng-updated.nix @@ -0,0 +1,21 @@ +{ lib, pyload-ng, fetchFromGitHub, python3Packages }: + +pyload-ng.overridePythonAttrs (oldAttrs: rec { + version = "0.5.0b3.dev93+git"; + + src = fetchFromGitHub { + owner = "pyload"; + repo = "pyload"; + rev = "3115740a2210fd57b5d050cd0850a0e61ec493ed"; # [DdownloadCom] fix #4537 + hash = "sha256-g1eEeNnr3Axtr+0BJzMcNQomTEX4EsUG1Jxt+huPyoc="; + }; + + # Add new dependencies required in newer versions + propagatedBuildInputs = (oldAttrs.propagatedBuildInputs or []) ++ (with python3Packages; [ + mini-racer + packaging + pydantic + flask-wtf + defusedxml + ]); +})