This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

1{ 2 config, 3 pkgs, 4 lib, 5 ... 6}: 7let 8 watchDirs = [ 9 "/var/lib/ipfs/download/movies" 10 "/var/lib/ipfs/download/shows" 11 "/var/lib/ipfs/download/games" 12 ]; 13 14 cidMapFile = "/var/lib/ipfs/cid-map.txt"; 15 16 pinWatcherScript = pkgs.writers.writeBash "ipfs-pin-watcher" '' 17 set -efu 18 19 IPFS="${pkgs.kubo}/bin/ipfs" 20 INOTIFYWAIT="${pkgs.inotify-tools}/bin/inotifywait" 21 CID_MAP="${cidMapFile}" 22 23 touch "$CID_MAP" 24 25 log() { 26 echo "[$(date -Iseconds)] $*" 27 } 28 29 add_file() { 30 local path="$1" 31 [ -f "$path" ] || return 0 32 case "$(basename "$path")" in 33 .* | *.part | *.tmp | *.synced.*) return 0 ;; 34 esac 35 36 log "Adding $path" 37 cid=$($IPFS add --nocopy --pin --quieter "$path" 2>/dev/null) || { 38 log "Failed to add $path" 39 return 0 40 } 41 log "Pinned $path -> $cid" 42 ${pkgs.gnused}/bin/sed -i "\|^[^ ]* $path$|d" "$CID_MAP" 43 echo "$cid $path" >> "$CID_MAP" 44 } 45 46 remove_file() { 47 local path="$1" 48 cid=$(${pkgs.gawk}/bin/awk -v p="$path" '$0 ~ p {print $1; exit}' "$CID_MAP") 49 if [ -n "$cid" ]; then 50 log "Unpinning $cid ($path)" 51 $IPFS pin rm "$cid" 2>/dev/null || true 52 ${pkgs.gnused}/bin/sed -i "\|^[^ ]* $path$|d" "$CID_MAP" 53 else 54 log "No CID found for removed file: $path" 55 fi 56 } 57 58 # initial sync 59 log "Starting initial sync..." 60 for dir in ${lib.escapeShellArgs watchDirs}; do 61 if [ -d "$dir" ]; then 62 ${pkgs.findutils}/bin/find "$dir" -type f | while read -r f; do 63 if ! ${pkgs.gnugrep}/bin/grep -q " $f$" "$CID_MAP" 2>/dev/null; then 64 add_file "$f" 65 fi 66 done 67 fi 68 done 69 log "Initial sync complete" 70 71 # clean stale entries 72 log "Cleaning stale entries..." 73 while IFS=' ' read -r cid path; do 74 if [ ! -f "$path" ]; then 75 log "Stale entry: $path (CID: $cid)" 76 $IPFS pin rm "$cid" 2>/dev/null || true 77 ${pkgs.gnused}/bin/sed -i "\|^[^ ]* $path$|d" "$CID_MAP" 78 fi 79 done < "$CID_MAP" 80 log "Cleanup complete" 81 82 # add all files in a newly appeared directory 83 scan_new_dir() { 84 local dir="$1" 85 log "Scanning new directory: $dir" 86 ${pkgs.findutils}/bin/find "$dir" -type f | while read -r f; do 87 add_file "$f" 88 done 89 } 90 91 # watch for changes 92 log "Watching directories: ${lib.concatStringsSep ", " watchDirs}" 93 $INOTIFYWAIT -m -r --format $'%w\t%e\t%f' \ 94 -e close_write \ 95 -e moved_to \ 96 -e moved_from \ 97 -e delete \ 98 -e create \ 99 ${lib.escapeShellArgs watchDirs} | 100 while IFS=$'\t' read -r dir event file; do 101 path="''${dir}''${file}" 102 case "$event" in 103 CREATE,ISDIR*|MOVED_TO,ISDIR*) 104 scan_new_dir "$path" 105 ;; 106 CLOSE_WRITE*|MOVED_TO*) 107 add_file "$path" 108 ;; 109 DELETE*|MOVED_FROM*) 110 remove_file "$path" 111 ;; 112 esac 113 done 114 ''; 115in 116{ 117 # symlink /var/download into IPFS root so --nocopy works 118 systemd.tmpfiles.rules = [ 119 "L+ /var/lib/ipfs/download - - - - /var/download" 120 ]; 121 122 services.kubo = { 123 enable = true; 124 settings = { 125 Experimental.FilestoreEnabled = true; 126 Addresses = { 127 API = [ 128 "/ip4/127.0.0.1/tcp/5001" 129 "/ip6/::1/tcp/5001" 130 ]; 131 Gateway = [ 132 "/ip4/0.0.0.0/tcp/8089" 133 "/ip6/::/tcp/8089" 134 ]; 135 }; 136 Datastore.StorageMax = "100GB"; 137 # limit bandwidth: 5MB/s out, 5MB/s in 138 Swarm.ConnMgr = { 139 LowWater = 20; 140 HighWater = 50; 141 GracePeriod = "10s"; 142 }; 143 Swarm.Transports.Network.TCP = true; 144 Swarm.Transports.Network.QUIC = false; 145 Swarm.ResourceMgr = { 146 Enabled = true; 147 MaxMemory = "256MB"; 148 }; 149 # disable relay to reduce overhead 150 Swarm.RelayClient.Enabled = false; 151 Swarm.RelayService.Enabled = false; 152 # reduce DHT overhead - client mode only announces, doesn't route for others 153 Routing.Type = "autoclient"; 154 }; 155 }; 156 157 boot.kernel.sysctl."fs.inotify.max_user_watches" = 1048576; 158 159 systemd.services.ipfs-pin-watcher = { 160 description = "Auto-pin files to IPFS using inotify"; 161 after = [ "ipfs.service" ]; 162 requires = [ "ipfs.service" ]; 163 wantedBy = [ "multi-user.target" ]; 164 serviceConfig = { 165 Environment = [ "IPFS_PATH=/var/lib/ipfs" ]; 166 ExecStart = pinWatcherScript; 167 Restart = "always"; 168 RestartSec = "10s"; 169 User = config.services.kubo.user; 170 Group = config.services.kubo.group; 171 SupplementaryGroups = [ "radio_container" ]; 172 }; 173 }; 174 175 networking.firewall.allowedTCPPorts = [ 176 4001 # IPFS swarm 177 8089 # IPFS gateway 178 ]; 179 networking.firewall.allowedUDPPorts = [ 180 4001 # IPFS swarm (QUIC) 181 ]; 182}