Compare commits
10 commits
545d7a0994
...
fa04def7a1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fa04def7a1 | ||
|
|
d5376704ca | ||
|
|
526d5d4e38 | ||
|
|
68620b27eb | ||
|
|
2999d1f556 | ||
|
|
83b46c93b8 | ||
|
|
beaeecc5f2 | ||
|
|
cd186314cc | ||
|
|
8267546811 | ||
|
|
2a15c8e8ad |
20 changed files with 156 additions and 114 deletions
|
|
@ -53,18 +53,18 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
job = {
|
job = {
|
||||||
backgroundTask.concurrency = 5;
|
backgroundTask.concurrency = 3;
|
||||||
faceDetection.concurrency = 1;
|
faceDetection.concurrency = 1;
|
||||||
library.concurrency = 7;
|
library.concurrency = 5;
|
||||||
metadataExtraction.concurrency = 7;
|
metadataExtraction.concurrency = 5;
|
||||||
migration.concurrency = 5;
|
migration.concurrency = 5;
|
||||||
notifications.concurrency = 5;
|
notifications.concurrency = 5;
|
||||||
search.concurrency = 5;
|
search.concurrency = 5;
|
||||||
sidecar.concurrency = 5;
|
sidecar.concurrency = 5;
|
||||||
ocr.concurrency = 1; # ML-intensive
|
ocr.concurrency = 1;
|
||||||
smartSearch.concurrency = 1; # ML-intensive
|
smartSearch.concurrency = 1;
|
||||||
thumbnailGeneration.concurrency = 5;
|
thumbnailGeneration.concurrency = 3;
|
||||||
videoConversion.concurrency = 2;
|
videoConversion.concurrency = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
library = {
|
library = {
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,6 @@
|
||||||
syncthing-custom.folders = {
|
syncthing-custom.folders = {
|
||||||
Credentials.enable = true;
|
Credentials.enable = true;
|
||||||
Documents.enable = true;
|
Documents.enable = true;
|
||||||
Media.enable = true;
|
|
||||||
Consume.enable = true;
|
|
||||||
Archive.enable = true;
|
Archive.enable = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -59,17 +57,16 @@
|
||||||
texlive.combined.scheme-full
|
texlive.combined.scheme-full
|
||||||
httpie
|
httpie
|
||||||
gnumake
|
gnumake
|
||||||
bind # DNS utilities (dig, nslookup, mdig)
|
bind
|
||||||
inetutils # Network utilities (telnet)
|
inetutils
|
||||||
netcat-gnu # Network connection utility
|
netcat-gnu
|
||||||
curl # HTTP client
|
curl
|
||||||
wget # Web downloader
|
wget
|
||||||
bandwhich # Terminal bandwidth utilization tool
|
bandwhich
|
||||||
ncdu
|
ncdu
|
||||||
delta
|
|
||||||
fastfetch
|
fastfetch
|
||||||
coreutils # GNU core utilities (base64, etc.)
|
coreutils
|
||||||
duti # Set default applications for file types (macOS)
|
duti
|
||||||
rsync
|
rsync
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@
|
||||||
|
|
||||||
screencapture = {
|
screencapture = {
|
||||||
disable-shadow = true;
|
disable-shadow = true;
|
||||||
location = "~/Consume/dcim";
|
location = "~/Downloads";
|
||||||
type = "png";
|
type = "png";
|
||||||
show-thumbnail = true;
|
show-thumbnail = true;
|
||||||
};
|
};
|
||||||
|
|
@ -174,8 +174,6 @@
|
||||||
"slidepilot"
|
"slidepilot"
|
||||||
"zotero"
|
"zotero"
|
||||||
"aerospace"
|
"aerospace"
|
||||||
"hiddenbar"
|
|
||||||
"keycastr"
|
|
||||||
"localsend"
|
"localsend"
|
||||||
"maccy"
|
"maccy"
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,6 @@
|
||||||
silent = true;
|
silent = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
# nixOS-specific alias
|
|
||||||
programs.zsh.shellAliases = {
|
programs.zsh.shellAliases = {
|
||||||
oss = "sudo nixos-rebuild switch --flake ~/.config/nix#$(hostname)";
|
oss = "sudo nixos-rebuild switch --flake ~/.config/nix#$(hostname)";
|
||||||
};
|
};
|
||||||
|
|
@ -35,12 +34,11 @@
|
||||||
httpie
|
httpie
|
||||||
gnumake
|
gnumake
|
||||||
rsync
|
rsync
|
||||||
bind # DNS utilities (dig, nslookup, mdig)
|
bind
|
||||||
iputils # Core network tools (ping, traceroute)
|
iputils
|
||||||
inetutils # Network utilities (telnet)
|
inetutils
|
||||||
netcat-gnu # Network connection utility
|
netcat-gnu
|
||||||
ncdu
|
ncdu
|
||||||
delta
|
|
||||||
fastfetch
|
fastfetch
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,7 @@ in
|
||||||
|
|
||||||
volumes = [
|
volumes = [
|
||||||
"/var/lib/immich/config:/config"
|
"/var/lib/immich/config:/config"
|
||||||
"/var/lib/immich/photos:/photos"
|
"/mnt/storage/photos:/photos"
|
||||||
"/mnt/storage/DCIM:/library:ro"
|
|
||||||
"${immichConfigFile}:/config/immich.json:ro"
|
"${immichConfigFile}:/config/immich.json:ro"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@
|
||||||
../home-default.nix
|
../home-default.nix
|
||||||
../../../modules/syncthing.nix
|
../../../modules/syncthing.nix
|
||||||
../../../modules/media/tool.nix
|
../../../modules/media/tool.nix
|
||||||
../../../modules/schedule.nix
|
|
||||||
];
|
];
|
||||||
|
|
||||||
syncthing-custom.folders = {
|
syncthing-custom.folders = {
|
||||||
|
|
@ -13,17 +12,6 @@
|
||||||
Documents = { enable = true; maxAgeDays = 30; };
|
Documents = { enable = true; maxAgeDays = 30; };
|
||||||
Media = { enable = true; maxAgeDays = 7; };
|
Media = { enable = true; maxAgeDays = 7; };
|
||||||
Archive = { enable = true; maxAgeDays = 30; };
|
Archive = { enable = true; maxAgeDays = 30; };
|
||||||
Consume = { enable = true; maxAgeDays = 7; };
|
|
||||||
DCIM = { enable = true; maxAgeDays = 7; path = "/mnt/storage/DCIM"; };
|
|
||||||
};
|
|
||||||
|
|
||||||
services.scheduled-commands.dcim-consume = {
|
|
||||||
enable = true;
|
|
||||||
description = "Move files in dcim consume folder to DCIM";
|
|
||||||
interval = "*-*-* *:00/15:00";
|
|
||||||
commands = [
|
|
||||||
"photo-move -d /home/yanlin/Consume/dcim /mnt/storage/DCIM"
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,17 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
photo = {
|
||||||
|
rule = "Host(`photo.home.yanlincs.com`)";
|
||||||
|
service = "photo";
|
||||||
|
tls = {
|
||||||
|
certResolver = "cloudflare";
|
||||||
|
domains = [{
|
||||||
|
main = "*.home.yanlincs.com";
|
||||||
|
}];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
services = {
|
services = {
|
||||||
|
|
@ -39,6 +50,15 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
photo = {
|
||||||
|
loadBalancer = {
|
||||||
|
serversTransport = "longTimeout";
|
||||||
|
servers = [{
|
||||||
|
url = "http://127.0.0.1:8080";
|
||||||
|
}];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -140,18 +140,21 @@
|
||||||
# Media server services
|
# Media server services
|
||||||
services.media-server = {
|
services.media-server = {
|
||||||
user = "yanlin";
|
user = "yanlin";
|
||||||
|
navidrome.enable = true;
|
||||||
deluge.enable = true;
|
deluge.enable = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
services.samba-custom.shares = {
|
services.samba-custom.shares = {
|
||||||
DCIM = "/mnt/storage/DCIM";
|
Downloads = "/home/yanlin/Downloads";
|
||||||
|
Media = "/home/yanlin/Media";
|
||||||
};
|
};
|
||||||
|
|
||||||
# Borg backup configuration
|
# Borg backup configuration
|
||||||
services.borg-client-custom = {
|
services.borg-client-custom = {
|
||||||
enable = false;
|
enable = true;
|
||||||
repositoryUrl = "ssh://helsinki-box/./nfss";
|
repositoryUrl = "ssh://helsinki-box/./nfss";
|
||||||
backupPaths = [
|
backupPaths = [
|
||||||
|
"/mnt/storage/photos/library"
|
||||||
];
|
];
|
||||||
backupFrequency = "*-*-* 01:00:00";
|
backupFrequency = "*-*-* 01:00:00";
|
||||||
retention = {
|
retention = {
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,6 @@
|
||||||
Documents = { enable = true; maxAgeDays = 30; };
|
Documents = { enable = true; maxAgeDays = 30; };
|
||||||
Media = { enable = true; maxAgeDays = 7; };
|
Media = { enable = true; maxAgeDays = 7; };
|
||||||
Archive = { enable = true; maxAgeDays = 30; };
|
Archive = { enable = true; maxAgeDays = 30; };
|
||||||
Consume = { enable = true; maxAgeDays = 7; };
|
|
||||||
DCIM = { enable = true; maxAgeDays = 7; path = "~/DCIM"; };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
services.scheduled-commands.aicloud-backup = {
|
services.scheduled-commands.aicloud-backup = {
|
||||||
|
|
|
||||||
|
|
@ -198,7 +198,6 @@
|
||||||
"/home/yanlin/Credentials"
|
"/home/yanlin/Credentials"
|
||||||
"/home/yanlin/Documents"
|
"/home/yanlin/Documents"
|
||||||
"/home/yanlin/Media"
|
"/home/yanlin/Media"
|
||||||
"/home/yanlin/DCIM"
|
|
||||||
];
|
];
|
||||||
backupFrequency = "*-*-* 00:00:00";
|
backupFrequency = "*-*-* 00:00:00";
|
||||||
retention = {
|
retention = {
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,8 @@
|
||||||
# Hardware configuration for VPS
|
{ lib, pkgs, modulesPath, ... }:
|
||||||
# This is a generic configuration suitable for most VPS providers
|
|
||||||
|
|
||||||
{ config, lib, pkgs, modulesPath, ... }:
|
|
||||||
|
|
||||||
{
|
{
|
||||||
imports = [ (modulesPath + "/profiles/qemu-guest.nix") ];
|
imports = [ (modulesPath + "/profiles/qemu-guest.nix") ];
|
||||||
|
|
||||||
# Boot configuration - common kernel modules for VPS environments
|
|
||||||
boot.initrd.availableKernelModules = [
|
boot.initrd.availableKernelModules = [
|
||||||
"ata_piix"
|
"ata_piix"
|
||||||
"uhci_hcd"
|
"uhci_hcd"
|
||||||
|
|
@ -23,20 +19,7 @@
|
||||||
boot.kernelModules = [ ];
|
boot.kernelModules = [ ];
|
||||||
boot.extraModulePackages = [ ];
|
boot.extraModulePackages = [ ];
|
||||||
|
|
||||||
# Filesystems are managed by disko configuration
|
|
||||||
# No filesystem declarations needed here
|
|
||||||
|
|
||||||
# No swap devices configured here - handled by disko
|
|
||||||
|
|
||||||
# Networking hardware
|
|
||||||
networking.useDHCP = lib.mkDefault true;
|
networking.useDHCP = lib.mkDefault true;
|
||||||
|
|
||||||
# Hardware-specific settings
|
|
||||||
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||||
|
|
||||||
# CPU microcode updates
|
|
||||||
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
|
||||||
|
|
||||||
# Enable firmware updates
|
|
||||||
hardware.enableRedistributableFirmware = lib.mkDefault true;
|
hardware.enableRedistributableFirmware = lib.mkDefault true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,28 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
music = {
|
||||||
|
rule = "Host(`music.yanlincs.com`)";
|
||||||
|
service = "music";
|
||||||
|
tls = {
|
||||||
|
certResolver = "cloudflare";
|
||||||
|
domains = [{
|
||||||
|
main = "*.yanlincs.com";
|
||||||
|
}];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
git = {
|
||||||
|
rule = "Host(`git.yanlincs.com`)";
|
||||||
|
service = "git";
|
||||||
|
tls = {
|
||||||
|
certResolver = "cloudflare";
|
||||||
|
domains = [{
|
||||||
|
main = "*.yanlincs.com";
|
||||||
|
}];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
services = {
|
services = {
|
||||||
|
|
@ -40,6 +62,22 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
music = {
|
||||||
|
loadBalancer = {
|
||||||
|
servers = [{
|
||||||
|
url = "http://10.1.1.152:4533";
|
||||||
|
}];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
git = {
|
||||||
|
loadBalancer = {
|
||||||
|
servers = [{
|
||||||
|
url = "http://127.0.0.1:3000";
|
||||||
|
}];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
../../../modules/podman.nix
|
../../../modules/podman.nix
|
||||||
../../../modules/traefik.nix
|
../../../modules/traefik.nix
|
||||||
../../../modules/borg/client.nix
|
../../../modules/borg/client.nix
|
||||||
|
../../../modules/git/server.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
# GRUB bootloader with UEFI support
|
# GRUB bootloader with UEFI support
|
||||||
|
|
@ -72,12 +73,18 @@
|
||||||
|
|
||||||
services.tailscale-custom.exitNode = true;
|
services.tailscale-custom.exitNode = true;
|
||||||
|
|
||||||
|
services.git-server-custom = {
|
||||||
|
enable = true;
|
||||||
|
domain = "git.yanlincs.com";
|
||||||
|
};
|
||||||
|
|
||||||
# Borg backup configuration
|
# Borg backup configuration
|
||||||
services.borg-client-custom = {
|
services.borg-client-custom = {
|
||||||
enable = true;
|
enable = true;
|
||||||
repositoryUrl = "ssh://helsinki-box/./vps";
|
repositoryUrl = "ssh://helsinki-box/./vps";
|
||||||
backupPaths = [
|
backupPaths = [
|
||||||
"/var/lib/mongodb"
|
"/var/lib/mongodb"
|
||||||
|
"/var/lib/forgejo"
|
||||||
];
|
];
|
||||||
backupFrequency = "*-*-* 03:00:00";
|
backupFrequency = "*-*-* 03:00:00";
|
||||||
retention = {
|
retention = {
|
||||||
|
|
|
||||||
|
|
@ -144,6 +144,8 @@ in
|
||||||
home.packages = [
|
home.packages = [
|
||||||
pkgs.claude-code
|
pkgs.claude-code
|
||||||
pkgs.poppler-utils
|
pkgs.poppler-utils
|
||||||
|
pkgs.pandoc
|
||||||
|
pkgs.yq-go
|
||||||
];
|
];
|
||||||
|
|
||||||
# Create global settings file (with permissions included)
|
# Create global settings file (with permissions included)
|
||||||
|
|
@ -159,6 +161,8 @@ in
|
||||||
- Projects may use flake + direnv for project-specific runtimes
|
- Projects may use flake + direnv for project-specific runtimes
|
||||||
- Common development tools (git, gh, ripgrep, jq, fzf, etc.) are globally available via nix
|
- Common development tools (git, gh, ripgrep, jq, fzf, etc.) are globally available via nix
|
||||||
- PDF reading is supported (poppler-utils installed)
|
- PDF reading is supported (poppler-utils installed)
|
||||||
|
- Document format conversion is supported (pandoc installed)
|
||||||
|
- YAML/TOML/XML processing is supported (yq-go installed)
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
{ config, pkgs, ... }:
|
{ config, pkgs, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
|
home.packages = [
|
||||||
|
pkgs.gh
|
||||||
|
];
|
||||||
|
|
||||||
programs.git-credential-oauth = {
|
programs.git-credential-oauth = {
|
||||||
enable = true;
|
enable = true;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
{ config, pkgs, lib, ... }:
|
{ config, pkgs, lib, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
|
home.packages = [ pkgs.delta ];
|
||||||
|
|
||||||
programs.lazygit = {
|
programs.lazygit = {
|
||||||
enable = true;
|
enable = true;
|
||||||
settings = {
|
settings = {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
{ config, lib, ... }:
|
# NOTE: After install, use the following command to create admin account.
|
||||||
|
# sudo -u forgejo forgejo --config /var/lib/forgejo/custom/conf/app.ini admin user create --admin --username <user> --password <pass> --email <email>
|
||||||
|
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.services.git-server-custom;
|
cfg = config.services.git-server-custom;
|
||||||
|
|
@ -24,6 +27,8 @@ in
|
||||||
};
|
};
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
|
environment.systemPackages = [ config.services.forgejo.package ];
|
||||||
|
|
||||||
services.forgejo = {
|
services.forgejo = {
|
||||||
enable = true;
|
enable = true;
|
||||||
lfs.enable = true;
|
lfs.enable = true;
|
||||||
|
|
@ -35,6 +40,7 @@ in
|
||||||
HTTP_ADDR = "127.0.0.1";
|
HTTP_ADDR = "127.0.0.1";
|
||||||
HTTP_PORT = cfg.httpPort;
|
HTTP_PORT = cfg.httpPort;
|
||||||
SSH_PORT = cfg.sshPort;
|
SSH_PORT = cfg.sshPort;
|
||||||
|
LANDING_PAGE = "/yanlin";
|
||||||
};
|
};
|
||||||
service.DISABLE_REGISTRATION = true;
|
service.DISABLE_REGISTRATION = true;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
# NOTE: Immich credentials file at: `~/.config/immich-env` with IMMICH_URL and IMMICH_APIKEY
|
||||||
|
|
||||||
{ config, pkgs, lib, ... }:
|
{ config, pkgs, lib, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
@ -7,10 +9,12 @@
|
||||||
shntool
|
shntool
|
||||||
cuetools
|
cuetools
|
||||||
flac
|
flac
|
||||||
|
zip
|
||||||
unzip
|
unzip
|
||||||
p7zip
|
p7zip
|
||||||
imagemagick
|
imagemagick
|
||||||
exiftool
|
exiftool
|
||||||
|
immich-go
|
||||||
];
|
];
|
||||||
|
|
||||||
programs.zsh.initContent = ''
|
programs.zsh.initContent = ''
|
||||||
|
|
@ -86,6 +90,29 @@
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function cbz-compress() {
|
||||||
|
local dir="''${1:-.}"
|
||||||
|
dir="$(cd "$dir" && pwd)"
|
||||||
|
mkdir -p "$dir/compressed"
|
||||||
|
find "$dir" -path "$dir/compressed" -prune -o -type f \( -iname '*.zip' -o -iname '*.cbz' \) -print | while read -r f; do
|
||||||
|
echo "Processing: $f"
|
||||||
|
local tmpdir=$(mktemp -d)
|
||||||
|
7z x -o"$tmpdir" -y "$f" > /dev/null
|
||||||
|
find "$tmpdir" -type f \( -iname '*.png' -o -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.gif' -o -iname '*.heic' -o -iname '*.heif' \) -print0 | xargs -0 -P4 -n1 sh -c '
|
||||||
|
img="$1"
|
||||||
|
outfile="''${img%.*}.webp"
|
||||||
|
${pkgs.imagemagick}/bin/magick "$img" -resize "1500>" -quality 75 "$outfile"
|
||||||
|
[ "$img" != "$outfile" ] && rm "$img"
|
||||||
|
' _
|
||||||
|
local relpath="''${f#$dir/}"
|
||||||
|
local outfile="$dir/compressed/$relpath"
|
||||||
|
mkdir -p "$(dirname "$outfile")"
|
||||||
|
(cd "$tmpdir" && zip -r -q "$outfile" .)
|
||||||
|
rm -rf "$tmpdir"
|
||||||
|
echo "Done: $outfile"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
function webp2png() {
|
function webp2png() {
|
||||||
local dir="''${1:-.}"
|
local dir="''${1:-.}"
|
||||||
find "$dir" -type f -iname '*.webp' | while read -r img; do
|
find "$dir" -type f -iname '*.webp' | while read -r img; do
|
||||||
|
|
@ -118,56 +145,24 @@
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
function photo-move() {
|
function photo-upload() {
|
||||||
local mode=copy
|
local envfile="$HOME/.config/immich-env"
|
||||||
if [[ "$1" == "-d" || "$1" == "--delete" ]]; then
|
if [[ ! -f "$envfile" ]]; then
|
||||||
mode=move; shift
|
echo "Missing $envfile" >&2
|
||||||
elif [[ "$1" == "-l" || "$1" == "--link" ]]; then
|
return 1
|
||||||
mode=link; shift
|
|
||||||
fi
|
fi
|
||||||
|
source "$envfile"
|
||||||
if [[ $# -ne 2 ]]; then
|
if [[ -z "$IMMICH_URL" || -z "$IMMICH_APIKEY" ]]; then
|
||||||
echo "Usage: photo-move [-d|--delete|-l|--link] <source_dir> <destination>"
|
echo "IMMICH_URL and IMMICH_APIKEY must be set in $envfile" >&2
|
||||||
echo " -d, --delete Move files instead of copying"
|
|
||||||
echo " -l, --link Hardlink instead of copying"
|
|
||||||
echo " photo-move /Volumes/CAMERA/DCIM ~/DCIM"
|
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local src="$1" dest="$2"
|
if [[ $# -eq 0 ]]; then
|
||||||
|
echo "Usage: photo-upload <source_dir>" >&2
|
||||||
if [[ ! -d "$src" ]]; then
|
|
||||||
echo "Source not found: $src" >&2
|
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local name raw_date target
|
immich-go upload from-folder --server="$IMMICH_URL" --api-key="$IMMICH_APIKEY" "$1"
|
||||||
while IFS= read -r -d "" file; do
|
|
||||||
name=$(basename "$file")
|
|
||||||
[[ "$name" == .* ]] && continue
|
|
||||||
|
|
||||||
raw_date=$(${pkgs.exiftool}/bin/exiftool -s3 -d '%Y-%m-%d' \
|
|
||||||
-DateTimeOriginal -CreateDate -MediaCreateDate "$file" 2>/dev/null | head -1)
|
|
||||||
|
|
||||||
if [[ ! "$raw_date" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ || "$raw_date" == "0000-00-00" ]]; then
|
|
||||||
raw_date=$(${pkgs.coreutils}/bin/date -d "@$(${pkgs.coreutils}/bin/stat -c '%Y' "$file")" +%Y-%m-%d)
|
|
||||||
fi
|
|
||||||
|
|
||||||
target="$dest/''${raw_date:0:4}/$raw_date"
|
|
||||||
mkdir -p "$target"
|
|
||||||
|
|
||||||
[[ -e "$target/$name" ]] && continue
|
|
||||||
|
|
||||||
case $mode in
|
|
||||||
move) mv "$file" "$target/$name" ;;
|
|
||||||
link) ln "$file" "$target/$name" ;;
|
|
||||||
*) cp -a "$file" "$target/$name" ;;
|
|
||||||
esac
|
|
||||||
done < <(find "$src" -type f \( \
|
|
||||||
-iname "*.mp4" -o -iname "*.mov" -o -iname "*.mts" -o -iname "*.m2ts" -o -iname "*.avi" \
|
|
||||||
-o -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" -o -iname "*.heic" -o -iname "*.heif" \
|
|
||||||
-o -iname "*.cr2" -o -iname "*.cr3" -o -iname "*.nef" -o -iname "*.arw" -o -iname "*.dng" -o -iname "*.raf" -o -iname "*.orf" -o -iname "*.rw2" \
|
|
||||||
\) -print0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function extract() {
|
function extract() {
|
||||||
|
|
@ -195,7 +190,7 @@
|
||||||
*.gz) gunzip -k "$file" ;;
|
*.gz) gunzip -k "$file" ;;
|
||||||
*.bz2) bunzip2 -k "$file" ;;
|
*.bz2) bunzip2 -k "$file" ;;
|
||||||
*.xz) unxz -k "$file" ;;
|
*.xz) unxz -k "$file" ;;
|
||||||
*.zip) unzip -q "$file" -d "$dest" ;;
|
*.zip|*.cbz) unzip -q "$file" -d "$dest" ;;
|
||||||
*.7z) 7z x "$file" -o"$dest" ;;
|
*.7z) 7z x "$file" -o"$dest" ;;
|
||||||
*.rar) 7z x "$file" -o"$dest" ;;
|
*.rar) 7z x "$file" -o"$dest" ;;
|
||||||
*)
|
*)
|
||||||
|
|
@ -235,7 +230,7 @@
|
||||||
case "''${file:l}" in
|
case "''${file:l}" in
|
||||||
*.tar.gz|*.tgz|*.tar.bz2|*.tbz2|*.tar.xz|*.txz|*.tar.zst|*.tzst|*.tar)
|
*.tar.gz|*.tgz|*.tar.bz2|*.tbz2|*.tar.xz|*.txz|*.tar.zst|*.tzst|*.tar)
|
||||||
tar -tf "$file" ;;
|
tar -tf "$file" ;;
|
||||||
*.zip) unzip -l "$file" ;;
|
*.zip|*.cbz) unzip -l "$file" ;;
|
||||||
*.7z) 7z l "$file" ;;
|
*.7z) 7z l "$file" ;;
|
||||||
*.rar) 7z l "$file" ;;
|
*.rar) 7z l "$file" ;;
|
||||||
*) echo "Unknown archive format: $file" >&2; return 1 ;;
|
*) echo "Unknown archive format: $file" >&2; return 1 ;;
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,11 @@ in
|
||||||
identityFile = "${keyDir}/hetzner";
|
identityFile = "${keyDir}/hetzner";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
"git.yanlincs.com" = {
|
||||||
|
user = "forgejo";
|
||||||
|
identityFile = "${keyDir}/hetzner";
|
||||||
|
};
|
||||||
|
|
||||||
"borg-box" = {
|
"borg-box" = {
|
||||||
hostname = "u518619.your-storagebox.de";
|
hostname = "u518619.your-storagebox.de";
|
||||||
user = "u518619";
|
user = "u518619";
|
||||||
|
|
|
||||||
|
|
@ -41,10 +41,8 @@ in
|
||||||
folders = {
|
folders = {
|
||||||
Credentials = mkFolderOptions "Credentials" {};
|
Credentials = mkFolderOptions "Credentials" {};
|
||||||
Documents = mkFolderOptions "Documents" { devices = pcDevices ++ serverDevices; };
|
Documents = mkFolderOptions "Documents" { devices = pcDevices ++ serverDevices; };
|
||||||
Media = mkFolderOptions "Media" { devices = lib.filter (d: d != "iphone") allDevices; };
|
Media = mkFolderOptions "Media" { devices = serverDevices ++ [ "ipad" ]; };
|
||||||
Archive = mkFolderOptions "Archive" {};
|
Archive = mkFolderOptions "Archive" {};
|
||||||
Consume = mkFolderOptions "Consume" {};
|
|
||||||
DCIM = mkFolderOptions "DCIM" { devices = serverDevices; };
|
|
||||||
};
|
};
|
||||||
enableGui = lib.mkOption {
|
enableGui = lib.mkOption {
|
||||||
type = lib.types.bool;
|
type = lib.types.bool;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue