diff --git a/config/immich.nix b/config/immich.nix index 4ca6228..0cb5577 100644 --- a/config/immich.nix +++ b/config/immich.nix @@ -53,18 +53,18 @@ }; job = { - backgroundTask.concurrency = 3; + backgroundTask.concurrency = 5; faceDetection.concurrency = 1; - library.concurrency = 5; - metadataExtraction.concurrency = 5; + library.concurrency = 7; + metadataExtraction.concurrency = 7; migration.concurrency = 5; notifications.concurrency = 5; search.concurrency = 5; sidecar.concurrency = 5; - ocr.concurrency = 1; - smartSearch.concurrency = 1; - thumbnailGeneration.concurrency = 3; - videoConversion.concurrency = 1; + ocr.concurrency = 1; # ML-intensive + smartSearch.concurrency = 1; # ML-intensive + thumbnailGeneration.concurrency = 5; + videoConversion.concurrency = 2; }; library = { diff --git a/hosts/darwin/home-default.nix b/hosts/darwin/home-default.nix index bd058a3..f455681 100644 --- a/hosts/darwin/home-default.nix +++ b/hosts/darwin/home-default.nix @@ -21,6 +21,8 @@ syncthing-custom.folders = { Credentials.enable = true; Documents.enable = true; + Media.enable = true; + Consume.enable = true; Archive.enable = true; }; @@ -57,16 +59,17 @@ texlive.combined.scheme-full httpie gnumake - bind - inetutils - netcat-gnu - curl - wget - bandwhich + bind # DNS utilities (dig, nslookup, mdig) + inetutils # Network utilities (telnet) + netcat-gnu # Network connection utility + curl # HTTP client + wget # Web downloader + bandwhich # Terminal bandwidth utilization tool ncdu + delta fastfetch - coreutils - duti + coreutils # GNU core utilities (base64, etc.) + duti # Set default applications for file types (macOS) rsync ]; diff --git a/hosts/darwin/system-default.nix b/hosts/darwin/system-default.nix index 422d708..182c514 100644 --- a/hosts/darwin/system-default.nix +++ b/hosts/darwin/system-default.nix @@ -101,7 +101,7 @@ screencapture = { disable-shadow = true; - location = "~/Downloads"; + location = "~/Consume/dcim"; type = "png"; show-thumbnail = true; }; @@ -174,6 +174,8 @@ "slidepilot" "zotero" "aerospace" + "hiddenbar" + "keycastr" "localsend" "maccy" ]; diff --git a/hosts/nixos/home-default.nix b/hosts/nixos/home-default.nix index f05b2f8..09afe7e 100644 --- a/hosts/nixos/home-default.nix +++ b/hosts/nixos/home-default.nix @@ -26,6 +26,7 @@ silent = true; }; + # nixOS-specific alias programs.zsh.shellAliases = { oss = "sudo nixos-rebuild switch --flake ~/.config/nix#$(hostname)"; }; @@ -34,11 +35,12 @@ httpie gnumake rsync - bind - iputils - inetutils - netcat-gnu + bind # DNS utilities (dig, nslookup, mdig) + iputils # Core network tools (ping, traceroute) + inetutils # Network utilities (telnet) + netcat-gnu # Network connection utility ncdu + delta fastfetch ]; } diff --git a/hosts/nixos/nfss/containers.nix b/hosts/nixos/nfss/containers.nix index 4b74247..36e88e6 100644 --- a/hosts/nixos/nfss/containers.nix +++ b/hosts/nixos/nfss/containers.nix @@ -17,7 +17,8 @@ in volumes = [ "/var/lib/immich/config:/config" - "/mnt/storage/photos:/photos" + "/var/lib/immich/photos:/photos" + "/mnt/storage/DCIM:/library:ro" "${immichConfigFile}:/config/immich.json:ro" ]; diff --git a/hosts/nixos/nfss/home.nix b/hosts/nixos/nfss/home.nix index 948c50d..8eea131 100644 --- a/hosts/nixos/nfss/home.nix +++ b/hosts/nixos/nfss/home.nix @@ -5,6 +5,7 @@ ../home-default.nix ../../../modules/syncthing.nix ../../../modules/media/tool.nix + ../../../modules/schedule.nix ]; syncthing-custom.folders = { @@ -12,6 +13,17 @@ Documents = { enable = true; maxAgeDays = 30; }; Media = { enable = true; maxAgeDays = 7; }; 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" + ]; }; } diff --git a/hosts/nixos/nfss/proxy.nix b/hosts/nixos/nfss/proxy.nix index b905d37..9a3a96a 100644 --- a/hosts/nixos/nfss/proxy.nix +++ b/hosts/nixos/nfss/proxy.nix @@ -27,17 +27,6 @@ }; }; - photo = { - rule = "Host(`photo.home.yanlincs.com`)"; - service = "photo"; - tls = { - certResolver = "cloudflare"; - domains = [{ - main = "*.home.yanlincs.com"; - }]; - }; - }; - }; services = { @@ -50,15 +39,6 @@ }; }; - photo = { - loadBalancer = { - serversTransport = "longTimeout"; - servers = [{ - url = "http://127.0.0.1:8080"; - }]; - }; - }; - }; }; diff --git a/hosts/nixos/nfss/system.nix b/hosts/nixos/nfss/system.nix index 06c3fc6..31b1c3d 100644 --- a/hosts/nixos/nfss/system.nix +++ b/hosts/nixos/nfss/system.nix @@ -140,21 +140,18 @@ # Media server services services.media-server = { user = "yanlin"; - navidrome.enable = true; deluge.enable = true; }; services.samba-custom.shares = { - Downloads = "/home/yanlin/Downloads"; - Media = "/home/yanlin/Media"; + DCIM = "/mnt/storage/DCIM"; }; # Borg backup configuration services.borg-client-custom = { - enable = true; + enable = false; repositoryUrl = "ssh://helsinki-box/./nfss"; backupPaths = [ - "/mnt/storage/photos/library" ]; backupFrequency = "*-*-* 01:00:00"; retention = { diff --git a/hosts/nixos/thinkpad/home.nix b/hosts/nixos/thinkpad/home.nix index 6d2c823..3aed2df 100644 --- a/hosts/nixos/thinkpad/home.nix +++ b/hosts/nixos/thinkpad/home.nix @@ -13,6 +13,8 @@ Documents = { enable = true; maxAgeDays = 30; }; Media = { enable = true; maxAgeDays = 7; }; Archive = { enable = true; maxAgeDays = 30; }; + Consume = { enable = true; maxAgeDays = 7; }; + DCIM = { enable = true; maxAgeDays = 7; path = "~/DCIM"; }; }; services.scheduled-commands.aicloud-backup = { diff --git a/hosts/nixos/thinkpad/system.nix b/hosts/nixos/thinkpad/system.nix index 467a882..e882200 100644 --- a/hosts/nixos/thinkpad/system.nix +++ b/hosts/nixos/thinkpad/system.nix @@ -198,6 +198,7 @@ "/home/yanlin/Credentials" "/home/yanlin/Documents" "/home/yanlin/Media" + "/home/yanlin/DCIM" ]; backupFrequency = "*-*-* 00:00:00"; retention = { diff --git a/hosts/nixos/vps/hardware-configuration.nix b/hosts/nixos/vps/hardware-configuration.nix index 3b24ed5..ecf2974 100644 --- a/hosts/nixos/vps/hardware-configuration.nix +++ b/hosts/nixos/vps/hardware-configuration.nix @@ -1,8 +1,12 @@ -{ lib, pkgs, modulesPath, ... }: +# Hardware configuration for VPS +# This is a generic configuration suitable for most VPS providers + +{ config, lib, pkgs, modulesPath, ... }: { imports = [ (modulesPath + "/profiles/qemu-guest.nix") ]; + # Boot configuration - common kernel modules for VPS environments boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" @@ -19,7 +23,20 @@ boot.kernelModules = [ ]; 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; + + # Hardware-specific settings 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; -} +} \ No newline at end of file diff --git a/hosts/nixos/vps/proxy.nix b/hosts/nixos/vps/proxy.nix index 1743577..bf542ab 100644 --- a/hosts/nixos/vps/proxy.nix +++ b/hosts/nixos/vps/proxy.nix @@ -27,28 +27,6 @@ }; }; - 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 = { @@ -62,22 +40,6 @@ }; }; - music = { - loadBalancer = { - servers = [{ - url = "http://10.1.1.152:4533"; - }]; - }; - }; - - git = { - loadBalancer = { - servers = [{ - url = "http://127.0.0.1:3000"; - }]; - }; - }; - }; }; diff --git a/hosts/nixos/vps/system.nix b/hosts/nixos/vps/system.nix index 0094da4..bf64008 100644 --- a/hosts/nixos/vps/system.nix +++ b/hosts/nixos/vps/system.nix @@ -10,7 +10,6 @@ ../../../modules/podman.nix ../../../modules/traefik.nix ../../../modules/borg/client.nix - ../../../modules/git/server.nix ]; # GRUB bootloader with UEFI support @@ -73,18 +72,12 @@ services.tailscale-custom.exitNode = true; - services.git-server-custom = { - enable = true; - domain = "git.yanlincs.com"; - }; - # Borg backup configuration services.borg-client-custom = { enable = true; repositoryUrl = "ssh://helsinki-box/./vps"; backupPaths = [ "/var/lib/mongodb" - "/var/lib/forgejo" ]; backupFrequency = "*-*-* 03:00:00"; retention = { diff --git a/modules/claude-code.nix b/modules/claude-code.nix index 05f837c..5cb55eb 100644 --- a/modules/claude-code.nix +++ b/modules/claude-code.nix @@ -144,8 +144,6 @@ in home.packages = [ pkgs.claude-code pkgs.poppler-utils - pkgs.pandoc - pkgs.yq-go ]; # Create global settings file (with permissions included) @@ -161,8 +159,6 @@ in - Projects may use flake + direnv for project-specific runtimes - Common development tools (git, gh, ripgrep, jq, fzf, etc.) are globally available via nix - PDF reading is supported (poppler-utils installed) - - Document format conversion is supported (pandoc installed) - - YAML/TOML/XML processing is supported (yq-go installed) ''; }; }; diff --git a/modules/git/home.nix b/modules/git/home.nix index 6a7e031..1e6b2cd 100644 --- a/modules/git/home.nix +++ b/modules/git/home.nix @@ -1,10 +1,6 @@ { config, pkgs, ... }: { - home.packages = [ - pkgs.gh - ]; - programs.git-credential-oauth = { enable = true; }; diff --git a/modules/git/lazygit.nix b/modules/git/lazygit.nix index a0a9a8b..262fcee 100644 --- a/modules/git/lazygit.nix +++ b/modules/git/lazygit.nix @@ -1,8 +1,6 @@ { config, pkgs, lib, ... }: { - home.packages = [ pkgs.delta ]; - programs.lazygit = { enable = true; settings = { diff --git a/modules/git/server.nix b/modules/git/server.nix index 62f09af..365e2ac 100644 --- a/modules/git/server.nix +++ b/modules/git/server.nix @@ -1,7 +1,4 @@ -# 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 --password --email - -{ config, lib, pkgs, ... }: +{ config, lib, ... }: let cfg = config.services.git-server-custom; @@ -27,8 +24,6 @@ in }; config = lib.mkIf cfg.enable { - environment.systemPackages = [ config.services.forgejo.package ]; - services.forgejo = { enable = true; lfs.enable = true; @@ -40,7 +35,6 @@ in HTTP_ADDR = "127.0.0.1"; HTTP_PORT = cfg.httpPort; SSH_PORT = cfg.sshPort; - LANDING_PAGE = "/yanlin"; }; service.DISABLE_REGISTRATION = true; }; diff --git a/modules/media/tool.nix b/modules/media/tool.nix index 20ea7dc..9869dbf 100644 --- a/modules/media/tool.nix +++ b/modules/media/tool.nix @@ -1,5 +1,3 @@ -# NOTE: Immich credentials file at: `~/.config/immich-env` with IMMICH_URL and IMMICH_APIKEY - { config, pkgs, lib, ... }: { @@ -9,12 +7,10 @@ shntool cuetools flac - zip unzip p7zip imagemagick exiftool - immich-go ]; programs.zsh.initContent = '' @@ -90,29 +86,6 @@ 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() { local dir="''${1:-.}" find "$dir" -type f -iname '*.webp' | while read -r img; do @@ -145,24 +118,56 @@ done } - function photo-upload() { - local envfile="$HOME/.config/immich-env" - if [[ ! -f "$envfile" ]]; then - echo "Missing $envfile" >&2 - return 1 + function photo-move() { + local mode=copy + if [[ "$1" == "-d" || "$1" == "--delete" ]]; then + mode=move; shift + elif [[ "$1" == "-l" || "$1" == "--link" ]]; then + mode=link; shift fi - source "$envfile" - if [[ -z "$IMMICH_URL" || -z "$IMMICH_APIKEY" ]]; then - echo "IMMICH_URL and IMMICH_APIKEY must be set in $envfile" >&2 + + if [[ $# -ne 2 ]]; then + echo "Usage: photo-move [-d|--delete|-l|--link] " + echo " -d, --delete Move files instead of copying" + echo " -l, --link Hardlink instead of copying" + echo " photo-move /Volumes/CAMERA/DCIM ~/DCIM" return 1 fi - if [[ $# -eq 0 ]]; then - echo "Usage: photo-upload " >&2 + local src="$1" dest="$2" + + if [[ ! -d "$src" ]]; then + echo "Source not found: $src" >&2 return 1 fi - immich-go upload from-folder --server="$IMMICH_URL" --api-key="$IMMICH_APIKEY" "$1" + local name raw_date target + 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() { @@ -190,7 +195,7 @@ *.gz) gunzip -k "$file" ;; *.bz2) bunzip2 -k "$file" ;; *.xz) unxz -k "$file" ;; - *.zip|*.cbz) unzip -q "$file" -d "$dest" ;; + *.zip) unzip -q "$file" -d "$dest" ;; *.7z) 7z x "$file" -o"$dest" ;; *.rar) 7z x "$file" -o"$dest" ;; *) @@ -230,7 +235,7 @@ case "''${file:l}" in *.tar.gz|*.tgz|*.tar.bz2|*.tbz2|*.tar.xz|*.txz|*.tar.zst|*.tzst|*.tar) tar -tf "$file" ;; - *.zip|*.cbz) unzip -l "$file" ;; + *.zip) unzip -l "$file" ;; *.7z) 7z l "$file" ;; *.rar) 7z l "$file" ;; *) echo "Unknown archive format: $file" >&2; return 1 ;; diff --git a/modules/ssh.nix b/modules/ssh.nix index 9ed224b..c773b11 100644 --- a/modules/ssh.nix +++ b/modules/ssh.nix @@ -51,11 +51,6 @@ in identityFile = "${keyDir}/hetzner"; }; - "git.yanlincs.com" = { - user = "forgejo"; - identityFile = "${keyDir}/hetzner"; - }; - "borg-box" = { hostname = "u518619.your-storagebox.de"; user = "u518619"; diff --git a/modules/syncthing.nix b/modules/syncthing.nix index 4bbf464..cabe71a 100644 --- a/modules/syncthing.nix +++ b/modules/syncthing.nix @@ -41,8 +41,10 @@ in folders = { Credentials = mkFolderOptions "Credentials" {}; Documents = mkFolderOptions "Documents" { devices = pcDevices ++ serverDevices; }; - Media = mkFolderOptions "Media" { devices = serverDevices ++ [ "ipad" ]; }; + Media = mkFolderOptions "Media" { devices = lib.filter (d: d != "iphone") allDevices; }; Archive = mkFolderOptions "Archive" {}; + Consume = mkFolderOptions "Consume" {}; + DCIM = mkFolderOptions "DCIM" { devices = serverDevices; }; }; enableGui = lib.mkOption { type = lib.types.bool;