feat: add nas host
This commit is contained in:
88
hosts/nas/configuration.nix
Normal file
88
hosts/nas/configuration.nix
Normal file
@@ -0,0 +1,88 @@
|
||||
# NAS host configuration
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
impermanence = builtins.fetchTarball "https://github.com/nix-community/impermanence/archive/master.tar.gz";
|
||||
in {
|
||||
nixpkgs.config.allowUnfree = true;
|
||||
|
||||
imports = [
|
||||
"${impermanence}/nixos.nix"
|
||||
./utils/bento.nix
|
||||
./utils/modules/sops.nix
|
||||
|
||||
./modules/pyload.nix
|
||||
./modules/jellyfin.nix
|
||||
|
||||
./hardware-configuration.nix
|
||||
];
|
||||
|
||||
nixpkgs.overlays = [
|
||||
(import ./utils/overlays/packages.nix)
|
||||
];
|
||||
|
||||
# Hostname
|
||||
networking.hostName = "nas";
|
||||
|
||||
# Timezone
|
||||
time.timeZone = "Europe/Vienna";
|
||||
console.keyMap = "de";
|
||||
|
||||
# SSH server
|
||||
services.openssh.enable = true;
|
||||
users.users.root.openssh.authorizedKeys.keys = [
|
||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7"
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius"
|
||||
];
|
||||
|
||||
# Firewall
|
||||
networking.firewall.enable = true;
|
||||
networking.firewall.allowedTCPPorts = [ 22 ];
|
||||
|
||||
# SOPS configuration
|
||||
sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
|
||||
sops.defaultSopsFile = ./secrets.yaml;
|
||||
|
||||
# Btrfs maintenance
|
||||
services.btrfs.autoScrub = {
|
||||
enable = true;
|
||||
interval = "monthly";
|
||||
fileSystems = [ "/nix" ];
|
||||
};
|
||||
|
||||
# Impermanence - persist important directories
|
||||
environment.persistence."/nix/persist/system" = {
|
||||
hideMounts = true;
|
||||
directories = [
|
||||
"/var/lib/pyload"
|
||||
"/var/lib/jellyfin"
|
||||
"/var/lib/downloads"
|
||||
"/var/lib/multimedia"
|
||||
"/var/log"
|
||||
"/var/lib/nixos"
|
||||
"/var/bento"
|
||||
"/root/.ssh"
|
||||
];
|
||||
files = [
|
||||
"/etc/machine-id"
|
||||
{ file = "/etc/ssh/ssh_host_ed25519_key"; parentDirectory = { mode = "u=rwx,g=,o="; }; }
|
||||
{ file = "/etc/ssh/ssh_host_ed25519_key.pub"; parentDirectory = { mode = "u=rwx,g=,o="; }; }
|
||||
{ file = "/etc/ssh/ssh_host_rsa_key"; parentDirectory = { mode = "u=rwx,g=,o="; }; }
|
||||
{ file = "/etc/ssh/ssh_host_rsa_key.pub"; parentDirectory = { mode = "u=rwx,g=,o="; }; }
|
||||
];
|
||||
};
|
||||
|
||||
# Nix settings
|
||||
nix = {
|
||||
settings = {
|
||||
auto-optimise-store = true;
|
||||
experimental-features = [ "nix-command" "flakes" ];
|
||||
};
|
||||
gc = {
|
||||
automatic = true;
|
||||
dates = "weekly";
|
||||
options = "--delete-older-than 14d";
|
||||
};
|
||||
};
|
||||
|
||||
system.stateVersion = "24.05";
|
||||
}
|
||||
1
hosts/nas/fleet.nix
Symbolic link
1
hosts/nas/fleet.nix
Symbolic link
@@ -0,0 +1 @@
|
||||
../../fleet.nix
|
||||
72
hosts/nas/hardware-configuration.nix
Normal file
72
hosts/nas/hardware-configuration.nix
Normal file
@@ -0,0 +1,72 @@
|
||||
# Hardware configuration for NAS
|
||||
# TODO: Update disk labels/UUIDs after installation
|
||||
{ config, lib, pkgs, modulesPath, ... }:
|
||||
{
|
||||
imports = [
|
||||
(modulesPath + "/installer/scan/not-detected.nix")
|
||||
];
|
||||
|
||||
boot.loader.systemd-boot = {
|
||||
enable = true;
|
||||
configurationLimit = 5;
|
||||
};
|
||||
boot.loader.efi.canTouchEfiVariables = true;
|
||||
boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usb_storage" "sd_mod" ];
|
||||
boot.initrd.kernelModules = [ ];
|
||||
boot.kernelModules = [ "kvm-intel" ];
|
||||
boot.extraModulePackages = [ ];
|
||||
|
||||
# Tmpfs root filesystem (ephemeral - resets on reboot)
|
||||
fileSystems."/" = {
|
||||
device = "none";
|
||||
fsType = "tmpfs";
|
||||
options = [ "size=8G" "mode=755" ];
|
||||
};
|
||||
|
||||
# Boot partition - EFI
|
||||
fileSystems."/boot" = {
|
||||
device = "/dev/disk/by-partlabel/BOOT";
|
||||
fsType = "vfat";
|
||||
};
|
||||
|
||||
fileSystems."/nix" = {
|
||||
device = "/dev/disk/by-partlabel/NIXOS";
|
||||
fsType = "btrfs";
|
||||
neededForBoot = true;
|
||||
options = [
|
||||
"subvol=@"
|
||||
"compress=zstd:1"
|
||||
"noatime"
|
||||
"commit=120"
|
||||
];
|
||||
};
|
||||
|
||||
fileSystems."/nix/store" = {
|
||||
device = "/dev/disk/by-partlabel/NIXOS";
|
||||
fsType = "btrfs";
|
||||
neededForBoot = true;
|
||||
options = [
|
||||
"subvol=@nix-store"
|
||||
"compress=zstd:1"
|
||||
"noatime"
|
||||
"commit=120"
|
||||
];
|
||||
};
|
||||
|
||||
fileSystems."/nix/persist" = {
|
||||
device = "/dev/disk/by-partlabel/NIXOS";
|
||||
fsType = "btrfs";
|
||||
neededForBoot = true;
|
||||
options = [
|
||||
"subvol=@nix-persist"
|
||||
"compress=zstd:1"
|
||||
"noatime"
|
||||
"commit=120"
|
||||
];
|
||||
};
|
||||
|
||||
# DHCP networking
|
||||
networking.useDHCP = lib.mkDefault true;
|
||||
|
||||
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
||||
}
|
||||
89
hosts/nas/modules/filebot-process.nix
Normal file
89
hosts/nas/modules/filebot-process.nix
Normal file
@@ -0,0 +1,89 @@
|
||||
{ pkgs }:
|
||||
|
||||
pkgs.writeShellScriptBin "filebot-process" ''
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# FileBot AMC script for automated media organization
|
||||
# Called by PyLoad's package_extracted hook with parameters:
|
||||
# $1 = package_id
|
||||
# $2 = package_name
|
||||
# $3 = download_folder (actual path to extracted files)
|
||||
# $4 = password (optional)
|
||||
|
||||
PACKAGE_ID="''${1:-}"
|
||||
PACKAGE_NAME="''${2:-unknown}"
|
||||
DOWNLOAD_DIR="''${3:-/var/lib/downloads}"
|
||||
PASSWORD="''${4:-}"
|
||||
|
||||
OUTPUT_DIR="/var/lib/multimedia"
|
||||
LOG_FILE="/var/lib/pyload/filebot-amc.log"
|
||||
EXCLUDE_LIST="/var/lib/pyload/filebot-exclude-list.txt"
|
||||
|
||||
# Ensure FileBot data directory exists
|
||||
mkdir -p /var/lib/pyload/.local/share/filebot/data
|
||||
mkdir -p "$(dirname "$LOG_FILE")"
|
||||
touch "$EXCLUDE_LIST"
|
||||
|
||||
# Install FileBot license if not already installed
|
||||
if [ ! -f /var/lib/pyload/.local/share/filebot/data/.license ]; then
|
||||
echo "$(date): Installing FileBot license..." >> "$LOG_FILE"
|
||||
${pkgs.filebot}/bin/filebot --license /var/lib/pyload/filebot-license.psm || true
|
||||
fi
|
||||
|
||||
echo "===========================================" >> "$LOG_FILE"
|
||||
echo "$(date): PyLoad package extracted hook triggered" >> "$LOG_FILE"
|
||||
echo "Package ID: $PACKAGE_ID" >> "$LOG_FILE"
|
||||
echo "Package Name: $PACKAGE_NAME" >> "$LOG_FILE"
|
||||
echo "Download Directory: $DOWNLOAD_DIR" >> "$LOG_FILE"
|
||||
echo "===========================================" >> "$LOG_FILE"
|
||||
|
||||
# Check if download directory exists and has media files
|
||||
if [ ! -d "$DOWNLOAD_DIR" ]; then
|
||||
echo "$(date): Download directory does not exist: $DOWNLOAD_DIR" >> "$LOG_FILE"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check if there are any video/media files to process
|
||||
if ! find "$DOWNLOAD_DIR" -type f \( -iname "*.mkv" -o -iname "*.mp4" -o -iname "*.avi" -o -iname "*.m4v" -o -iname "*.mov" \) -print -quit | grep -q .; then
|
||||
echo "$(date): No media files found in: $DOWNLOAD_DIR" >> "$LOG_FILE"
|
||||
echo "$(date): Skipping FileBot processing" >> "$LOG_FILE"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "$(date): Starting FileBot processing" >> "$LOG_FILE"
|
||||
|
||||
# Run FileBot AMC script
|
||||
set +e # Temporarily disable exit on error to capture exit code
|
||||
${pkgs.filebot}/bin/filebot \
|
||||
-script fn:amc \
|
||||
--output "$OUTPUT_DIR" \
|
||||
--action move \
|
||||
--conflict auto \
|
||||
-non-strict \
|
||||
--log-file "$LOG_FILE" \
|
||||
--def \
|
||||
excludeList="$EXCLUDE_LIST" \
|
||||
movieFormat="$OUTPUT_DIR/movies/{n} ({y})/{n} ({y}) - {vf}" \
|
||||
seriesFormat="$OUTPUT_DIR/tv-shows/{n}/Season {s.pad(2)}/{n} - {s00e00} - {t}" \
|
||||
ut_dir="$DOWNLOAD_DIR" \
|
||||
ut_kind=multi \
|
||||
clean=y \
|
||||
skipExtract=y
|
||||
|
||||
FILEBOT_EXIT_CODE=$?
|
||||
set -e # Re-enable exit on error
|
||||
|
||||
if [ $FILEBOT_EXIT_CODE -ne 0 ]; then
|
||||
echo "$(date): FileBot processing failed with exit code $FILEBOT_EXIT_CODE" >> "$LOG_FILE"
|
||||
exit 0 # Don't fail the hook even if FileBot fails
|
||||
fi
|
||||
|
||||
echo "$(date): FileBot processing completed successfully" >> "$LOG_FILE"
|
||||
|
||||
# Clean up any remaining empty directories
|
||||
find "$DOWNLOAD_DIR" -type d -empty -delete 2>/dev/null || true
|
||||
|
||||
echo "$(date): All processing completed" >> "$LOG_FILE"
|
||||
exit 0
|
||||
''
|
||||
51
hosts/nas/modules/jellyfin.nix
Normal file
51
hosts/nas/modules/jellyfin.nix
Normal file
@@ -0,0 +1,51 @@
|
||||
{ lib, pkgs, ... }: {
|
||||
# Intel graphics support for hardware transcoding
|
||||
hardware.graphics = {
|
||||
enable = true;
|
||||
extraPackages = with pkgs; [
|
||||
intel-media-driver
|
||||
vpl-gpu-rt
|
||||
intel-compute-runtime
|
||||
];
|
||||
};
|
||||
|
||||
# Set VA-API driver to iHD (modern Intel driver)
|
||||
environment.sessionVariables = {
|
||||
LIBVA_DRIVER_NAME = "iHD";
|
||||
};
|
||||
|
||||
# Jellyfin user with render/video groups for GPU access
|
||||
users.users.jellyfin = {
|
||||
isSystemUser = true;
|
||||
group = "jellyfin";
|
||||
home = "/var/lib/jellyfin";
|
||||
createHome = true;
|
||||
extraGroups = [ "render" "video" ];
|
||||
};
|
||||
users.groups.jellyfin = {};
|
||||
|
||||
# Create jellyfin directory
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /var/lib/jellyfin 0755 jellyfin jellyfin - -"
|
||||
];
|
||||
|
||||
services.jellyfin = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
};
|
||||
|
||||
# Override systemd hardening for GPU access
|
||||
systemd.services.jellyfin = {
|
||||
serviceConfig = {
|
||||
PrivateUsers = lib.mkForce false; # Disable user namespacing - breaks GPU device access
|
||||
DeviceAllow = [
|
||||
"/dev/dri/card0 rw"
|
||||
"/dev/dri/renderD128 rw"
|
||||
];
|
||||
SupplementaryGroups = [ "render" "video" ]; # Critical: Explicit group membership for GPU access
|
||||
};
|
||||
environment = {
|
||||
LIBVA_DRIVER_NAME = "iHD"; # Ensure service sees this variable
|
||||
};
|
||||
};
|
||||
}
|
||||
104
hosts/nas/modules/pyload.nix
Normal file
104
hosts/nas/modules/pyload.nix
Normal file
@@ -0,0 +1,104 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
let
|
||||
filebotScript = pkgs.callPackage ./filebot-process.nix {};
|
||||
in
|
||||
{
|
||||
nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [
|
||||
"unrar"
|
||||
"filebot"
|
||||
];
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
unrar # Required for RAR archive extraction
|
||||
p7zip # Required for 7z and other archive formats
|
||||
];
|
||||
|
||||
# Create directory structure
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /var/lib/downloads 0755 pyload pyload - -"
|
||||
"d /var/lib/multimedia 0775 root jellyfin - -"
|
||||
"d /var/lib/multimedia/movies 0775 jellyfin jellyfin - -"
|
||||
"d /var/lib/multimedia/tv-shows 0775 jellyfin jellyfin - -"
|
||||
"d /var/lib/multimedia/music 0755 jellyfin jellyfin - -"
|
||||
|
||||
# PyLoad hook scripts directory
|
||||
"d /var/lib/pyload/config 0755 pyload pyload - -"
|
||||
"d /var/lib/pyload/config/scripts 0755 pyload pyload - -"
|
||||
"d /var/lib/pyload/config/scripts/package_extracted 0755 pyload pyload - -"
|
||||
"L+ /var/lib/pyload/config/scripts/package_extracted/filebot-process.sh - - - - ${filebotScript}/bin/filebot-process"
|
||||
];
|
||||
|
||||
# FileBot license secret (only if secrets.yaml exists)
|
||||
sops.secrets.filebot-license = {
|
||||
mode = "0440";
|
||||
owner = "pyload";
|
||||
group = "pyload";
|
||||
path = "/var/lib/pyload/filebot-license.psm";
|
||||
};
|
||||
|
||||
# PyLoad user with jellyfin group membership for multimedia access
|
||||
users.users.pyload = {
|
||||
isSystemUser = true;
|
||||
group = "pyload";
|
||||
home = "/var/lib/pyload";
|
||||
createHome = true;
|
||||
extraGroups = [ "jellyfin" ];
|
||||
};
|
||||
users.groups.pyload = {};
|
||||
|
||||
services.pyload = {
|
||||
enable = true;
|
||||
downloadDirectory = "/var/lib/downloads";
|
||||
listenAddress = "0.0.0.0";
|
||||
port = 8000;
|
||||
};
|
||||
|
||||
# Configure pyload service
|
||||
systemd.services.pyload = {
|
||||
# Add extraction tools to service PATH
|
||||
path = with pkgs; [
|
||||
unrar # For RAR extraction
|
||||
p7zip # For 7z extraction
|
||||
];
|
||||
|
||||
environment = {
|
||||
# Disable SSL certificate verification
|
||||
PYLOAD__GENERAL__SSL_VERIFY = "0";
|
||||
|
||||
# Download speed limiting (150 Mbit/s = 19200 KiB/s)
|
||||
PYLOAD__DOWNLOAD__LIMIT_SPEED = "1";
|
||||
PYLOAD__DOWNLOAD__MAX_SPEED = "19200";
|
||||
|
||||
# Enable ExtractArchive plugin
|
||||
PYLOAD__EXTRACTARCHIVE__ENABLED = "1";
|
||||
PYLOAD__EXTRACTARCHIVE__DELETE = "1";
|
||||
PYLOAD__EXTRACTARCHIVE__DELTOTRASH = "0";
|
||||
PYLOAD__EXTRACTARCHIVE__REPAIR = "1";
|
||||
PYLOAD__EXTRACTARCHIVE__RECURSIVE = "1";
|
||||
PYLOAD__EXTRACTARCHIVE__FULLPATH = "1";
|
||||
|
||||
# Enable ExternalScripts plugin for hooks
|
||||
PYLOAD__EXTERNALSCRIPTS__ENABLED = "1";
|
||||
PYLOAD__EXTERNALSCRIPTS__UNLOCK = "1"; # Run hooks asynchronously
|
||||
};
|
||||
|
||||
serviceConfig = {
|
||||
# Bind mount multimedia directory as writable for FileBot hook scripts
|
||||
BindPaths = [ "/var/lib/multimedia" ];
|
||||
|
||||
# Override SystemCallFilter to allow @resources syscalls
|
||||
# FileBot (Java) needs resource management syscalls like setpriority
|
||||
# during cleanup operations. Still block privileged syscalls for security.
|
||||
SystemCallFilter = lib.mkForce [
|
||||
"@system-service"
|
||||
"@resources" # Explicitly allow resource management syscalls
|
||||
"~@privileged" # Still block privileged operations
|
||||
"fchown" # Re-allow fchown for FileBot file operations
|
||||
"fchown32" # 32-bit compatibility
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
# Open firewall for PyLoad web interface
|
||||
networking.firewall.allowedTCPPorts = [ 8000 ];
|
||||
}
|
||||
43
hosts/nas/secrets.yaml
Normal file
43
hosts/nas/secrets.yaml
Normal file
@@ -0,0 +1,43 @@
|
||||
filebot-license: ENC[AES256_GCM,data:7fmczgcLOp/tkdoMVGfwESam9NwhZrNJXNcnebMKfilEKc81V4fdzS3/hxlueun2At6047UAdDi+6jAO3FvTmzmpmOFnrQxhojUKX2kj9SMSuDlskqxNt04O8wpGy69T8uOeV3ZUcRASzmfzQmuVU+zPKoIV2nq34mhXeIl17V22ZvoTDtFLs2w3IzxtKMZqLtDH4GZ4dkRcQBFcGY96T9R4CLcBqyZeBYb15ZaVLN9dHpQfExtpsBMVB3NikdWgUK9IAbjff1Xtkn+RT9gpQggCyQUl6UbtGqienbCq8ATORe1f89s+q6x/KneC5bdVZKQ4IqZrzDcuQ5aEJUEslc3aVITI3THEBWLOhYANy/4mMyw7R2KRIiHLrXAiiuxi3JumBvev27S6ilKdNo2By8OsbAB/Oj2YvDc5EBTePLCU0OloHIMSxWv5VkLQ2rM94bYtqXN269Lv6w4zmpOF0QblrvtoXnhhf4BQyf9owRDuNMrbp3Iu9Xnj87GoQVnulpwsMSifFxIibd94sRxS/N/5JTTih3Twj/Y8ZpmvoR8t9vCJ14vwBbMXheBpIYzxTk1phZKK1jLfi49DpWudop6iKNOCZdMeXxVRyAfTpOZSGqmdmsqOEDZESCnOAcNYlTxXmLmTdeqJfvTzsnWUi6kbbMYzaSaUlG7UB+RYnt97mcT5NtmbwCRDuFEOdqKGiR/vi7natH8VXe6nlY7xZxei0kkKAhIwyXV+mj/xurbQP3SuyYZriO2luCfuazxmVR0FpBqv+UZ6LwldmQ5e+O7hveYd+o1IjqjT67pVgLyFo1XY95Phq4/vFNvcZKhP7dqKlddkO5RCqjxHCmLowPSUfO2G4k7NV9/UioudATZnWGBpMfSp0pSuD9GXrPg=,iv:5BP77BRudjLiIKI5973BWbQlftupAdfd/aqFeN7DYLM=,tag:q2CAzGZ8lXPS41Uf2NjJTg==,type:str]
|
||||
sops:
|
||||
age:
|
||||
- recipient: age14grjcxaq4h55yfnjxvnqhtswxhj9sfdcvyas4lwvpa8py27pjy2sv3g6v7
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBQWUI4YUsvODJtdTN4NDNn
|
||||
QkFDVmFSV2Q1Q04rcWtiazZEMzFCYzRJMEJrCjM5RE41TjE0eURrNi9iQnBTR1Fy
|
||||
SENYYmloSjI1c25pck5CSTJZTDhCeTQKLS0tIEs0SnFSNUdsdzZWS0loTEdBN1RD
|
||||
ZnhBREtlR3o4VTVMZ1RtY1lVbG40YkUK2isPCoJSTQ6CUbHftSDoUZC8MMTqr512
|
||||
lCoeGQqnArTO8CWDJxIxRczooTo4mW7vDqD7idWdPgOdWZI8hWPE5Q==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1exny8unxynaw03yu8ppahu5z28uermghr8ag34e7kdqnaduq9stsyettzz
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBwdnJIeWh1RkhvLzF2QUlm
|
||||
ZmNHaFpzL0M3eUdCdk1GL1g2MTdtdTdjVmdjCmVRTWJsajhKT0E5STN2SEUzWHFa
|
||||
ak1NelloQnNiY3FaUm9oVGg5eit2eTAKLS0tIEoxcURjUkJsRENtblZpKy9QT0gx
|
||||
ME5kM1EwYUFNMVFkT3VWZmpGSzRoWFUKzGNK5FzRWiY+E1Je6l0veoN5Z3K2TFMY
|
||||
pm9+FGuYs+wxSrhLwajITj+NuH0+zK81mrYsugH+6OTNb7cDbLgh/g==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1v6p8dan2t3w9h94fz4flldl32082j3s9x6zqq7u5j66keth9aphsd6pvch
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBlWCs0a3EvZC9sWmI5S2tU
|
||||
aFpRMVlrZG1zL1ZJSklJMkNQY1RLMW53YUhZCjNpQ1pHUE0yVUxleVovcVRLMFNh
|
||||
amVFTnJteW8xRjlFY29HWkJrcVJiQzgKLS0tIFJrWWloc2ZWdGdPNlNQM2szTkZI
|
||||
Zk42dFgrcUJOa3UwSDB3MnpMcVRLdmsKOKbF18HnowVhiEHO2B+BZqpM8Oc8vbDh
|
||||
hczIpcezwMvv96L2/seX86Hv5mEAQvwN2CVA+sknnDL1XNA/2Ng9cw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1x3elhtccp4u8ha5ry32juj9fkpg0qg7qqx4gduuehgwwnnhcxp8s892hek
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB6L1pVc2lRYVVnMU1uR1hn
|
||||
aldPODkvTVFzNDRuWWFTTU5jU0dyOHFMNkZBCnQ0ZGxUcGR5d0FqK2pOenJzSEN4
|
||||
ak12VXhQSnZlbSs1V3BxZnBIQ0xKV1EKLS0tIEkrc00wTzJzVjVDd0o4WHNQVDV6
|
||||
WGlpR1kvdXFnMkxOQVVuL3pIckdLRGcK+xoZE63l+9mlR5ufN9kEtgKEHdIUcGbI
|
||||
CpNhd8RE23tPKaVa0XbQA3bMqc1J9jST3vSWWewexwdLvfjrooSFZw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2025-11-28T18:05:54Z"
|
||||
mac: ENC[AES256_GCM,data:rmGDt0ZvZ8S//X1sqzkM9GdsoLBTB9dUprWdVN5M9F4/Zpq6Mpyk04VdGxYz421Gi+AsvhAkBaKi+XJjiEjRf9dYON/N18bWeRe3mJMLVOOoxGz+PQOeAuCyphZEKsCkae79WtbRZqONkU+kSqT5ED6iLjhOpLn1h6Cuw4wV1Xc=,iv:XWjRyxlGP4a14eUaJvZpizy2UiCSIi/PIUyaZg6GCJY=,tag:ZNp/U1O3wkcb8o5s1USrsw==,type:str]
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.11.0
|
||||
1
hosts/nas/utils
Symbolic link
1
hosts/nas/utils
Symbolic link
@@ -0,0 +1 @@
|
||||
../../utils
|
||||
Reference in New Issue
Block a user