Clean up: remove stale scripts/docs, fix debug prints, update PLAN.md
Deploy Dashboard / deploy (push) Successful in 37s
Deploy Dashboard / deploy (push) Successful in 37s
This commit is contained in:
@@ -45,19 +45,25 @@ Existing VPS (158.101.140.85): xray VLESS+REALITY on :443 — untouched
|
|||||||
|
|
||||||
```
|
```
|
||||||
nas-tools/
|
nas-tools/
|
||||||
|
PLAN.md
|
||||||
|
backup.sh # Daily backup cron script
|
||||||
|
notify.sh # Telegram notification utility
|
||||||
dashboard/
|
dashboard/
|
||||||
docker-compose.yml # Dashboard + docker-socket-proxy
|
docker-compose.yml
|
||||||
Dockerfile
|
Dockerfile
|
||||||
.env.example
|
.env.example
|
||||||
backend/
|
backend/
|
||||||
main.py
|
main.py
|
||||||
config.py
|
config.py
|
||||||
|
auth.py
|
||||||
requirements.txt
|
requirements.txt
|
||||||
routers/
|
routers/
|
||||||
|
auth.py
|
||||||
docker.py
|
docker.py
|
||||||
gitea.py
|
gitea.py
|
||||||
files.py
|
files.py
|
||||||
terminal.py
|
terminal.py
|
||||||
|
system.py
|
||||||
frontend/
|
frontend/
|
||||||
package.json
|
package.json
|
||||||
vite.config.js
|
vite.config.js
|
||||||
@@ -83,9 +89,6 @@ nas-tools/
|
|||||||
docker-compose.yml
|
docker-compose.yml
|
||||||
openclaw/
|
openclaw/
|
||||||
docker-compose.yml
|
docker-compose.yml
|
||||||
|
|
||||||
cloud-monitor/
|
|
||||||
oci-amd-monitor.py # New: grab AMD free-tier instance
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Implementation Phases
|
## Implementation Phases
|
||||||
@@ -154,21 +157,21 @@ cloud-monitor/
|
|||||||
35. ~~Telegram failure alerts~~ — Done (sources creds from nas-dashboard .env)
|
35. ~~Telegram failure alerts~~ — Done (sources creds from nas-dashboard .env)
|
||||||
36. Periodic restore test to verify backups work
|
36. Periodic restore test to verify backups work
|
||||||
|
|
||||||
### Phase 10 — Monitoring & Alerts (partial)
|
### Phase 10 — Monitoring & Alerts ✅
|
||||||
36. ~~Add system stats to dashboard overview: CPU, RAM, disk usage~~ — Done
|
36. ~~Add system stats to dashboard overview: CPU, RAM, disk usage~~ — Done
|
||||||
37. ~~Container health checks in docker-compose files~~ — Done
|
37. ~~Container health checks in docker-compose files~~ — Done
|
||||||
38. Notification on failure (Telegram bot or email)
|
38. ~~Notification on failure (Telegram bot)~~ — Done (container monitor + failed login alerts)
|
||||||
|
|
||||||
### Phase 11 — Polish (partial)
|
### Phase 11 — Polish ✅
|
||||||
39. ~~Light/dark theme toggle~~ — Done
|
39. ~~Light/dark theme toggle~~ — Done
|
||||||
40. ~~Add Jellyfin link to dashboard sidebar (port 8096)~~ — Done (replaced Emby)
|
40. ~~Add Jellyfin link to dashboard sidebar (port 8096)~~ — Done (replaced Emby)
|
||||||
|
|
||||||
### Phase 12 — Additional Services
|
### Phase 12 — Additional Services ✅
|
||||||
41. Deploy Audiobookshelf on port 13378 — Done, add to dashboard sidebar
|
41. ~~Deploy Audiobookshelf on port 13378~~ — Done, in dashboard sidebar
|
||||||
42. Deploy Stirling PDF on port 8030 — Done, add to dashboard sidebar
|
42. ~~Deploy Stirling PDF on port 8030~~ — Done, in dashboard sidebar
|
||||||
43. Deploy Vaultwarden on port 8222 — Done, add to dashboard sidebar
|
43. ~~Deploy Vaultwarden on port 8222~~ — Done, in dashboard sidebar
|
||||||
44. Deploy Watchtower for auto-updates — Done (internal, no sidebar link needed)
|
44. ~~Deploy Watchtower for auto-updates~~ — Done (internal, no sidebar link needed)
|
||||||
45. Deploy Speedtest on port 8080 — Done, already in dashboard sidebar
|
45. ~~Deploy Speedtest on port 8080~~ — Done, in dashboard sidebar
|
||||||
|
|
||||||
### Phase 13 — Off-site Backup
|
### Phase 13 — Off-site Backup
|
||||||
46. Add cloud backup (OneDrive or Google Drive) for critical data
|
46. Add cloud backup (OneDrive or Google Drive) for critical data
|
||||||
|
|||||||
@@ -1,148 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Aggressive Free System Data (351GB)
|
|
||||||
# When normal methods don't work
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Aggressive Free System Data (351GB) ==="
|
|
||||||
echo ""
|
|
||||||
echo "Since normal methods didn't work, we need to be more aggressive."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
FREE_SPACE_BEFORE=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB_BEFORE=$(echo "scale=2; $FREE_SPACE_BEFORE / 1024 / 1024" | bc)
|
|
||||||
echo "Current free space: ${FREE_SPACE_GB_BEFORE}GB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🔍 Checking Time Machine configuration..."
|
|
||||||
TM_DEST=$(defaults read /Library/Preferences/com.apple.TimeMachine LastDestinationID 2>/dev/null || echo "NONE")
|
|
||||||
if [ "$TM_DEST" != "NONE" ]; then
|
|
||||||
echo " ⚠️ Time Machine destination still configured: $TM_DEST"
|
|
||||||
echo " This means snapshots may still be created!"
|
|
||||||
echo ""
|
|
||||||
echo " You MUST remove it in System Settings:"
|
|
||||||
echo " System Settings → Time Machine → Remove backup disk"
|
|
||||||
echo ""
|
|
||||||
read -p " Have you removed it? (y/n) " -n 1 -r
|
|
||||||
echo ""
|
|
||||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
||||||
echo " ⚠️ Please remove it first!"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo " ✅ Time Machine destination removed"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🔧 Method 1: Force delete all local snapshots..."
|
|
||||||
SNAPSHOTS=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$")
|
|
||||||
if [ -n "$SNAPSHOTS" ]; then
|
|
||||||
echo "$SNAPSHOTS" | while read snapshot; do
|
|
||||||
if [ -n "$snapshot" ]; then
|
|
||||||
SNAP_DATE=$(echo "$snapshot" | sed 's/.*\.\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}\)\.backup/\1/')
|
|
||||||
if [ -n "$SNAP_DATE" ]; then
|
|
||||||
echo " Deleting: $snapshot"
|
|
||||||
sudo tmutil deletelocalsnapshots "$SNAP_DATE" 2>&1 || echo " ⚠️ Failed (ghost entry)"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
else
|
|
||||||
echo " No snapshots found"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🔧 Method 2: Aggressive thinning (keep only 1GB, 1 day)..."
|
|
||||||
sudo tmutil thinlocalsnapshots / 1000000000 1 2>&1
|
|
||||||
echo " ✓ Completed"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🔧 Method 3: Disable Time Machine completely..."
|
|
||||||
sudo tmutil disable 2>/dev/null || echo " ⚠️ Could not disable (may already be disabled)"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🔧 Method 4: Clear Time Machine database..."
|
|
||||||
echo " ⚠️ This will clear Time Machine's local database"
|
|
||||||
read -p " Proceed? (y/n) " -n 1 -r
|
|
||||||
echo ""
|
|
||||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
||||||
# Backup first
|
|
||||||
sudo cp -r /Library/Preferences/com.apple.TimeMachine.plist /Library/Preferences/com.apple.TimeMachine.plist.backup 2>/dev/null || true
|
|
||||||
echo " Backed up preferences"
|
|
||||||
|
|
||||||
# Clear local snapshots database
|
|
||||||
sudo rm -rf /System/Volumes/Data/.timemachine/* 2>/dev/null || true
|
|
||||||
echo " ✓ Cleared Time Machine local data"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🔧 Method 5: Force filesystem sync and purge..."
|
|
||||||
sync
|
|
||||||
if command -v purge &> /dev/null; then
|
|
||||||
sudo purge
|
|
||||||
echo " ✓ Purged"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🔧 Method 6: Use macOS storage optimization..."
|
|
||||||
echo ""
|
|
||||||
echo " ⚠️ CRITICAL: You need to use macOS's built-in tool:"
|
|
||||||
echo ""
|
|
||||||
echo " 1. Apple Menu → About This Mac → Storage"
|
|
||||||
echo " 2. Click 'Manage...'"
|
|
||||||
echo " 3. Look for 'Optimize Storage' or similar option"
|
|
||||||
echo " 4. This will release purgeable space"
|
|
||||||
echo ""
|
|
||||||
echo " OR use Terminal:"
|
|
||||||
echo " sudo tmutil thinlocalsnapshots / 1000000000 1"
|
|
||||||
echo " sudo purge"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "⏳ Waiting for system to update..."
|
|
||||||
sleep 15
|
|
||||||
|
|
||||||
# Check results
|
|
||||||
FREE_SPACE_AFTER=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB_AFTER=$(echo "scale=2; $FREE_SPACE_AFTER / 1024 / 1024" | bc)
|
|
||||||
FREED_GB=$(echo "scale=2; $FREE_SPACE_GB_AFTER - $FREE_SPACE_GB_BEFORE" | bc)
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "=== Results ==="
|
|
||||||
echo " Before: ${FREE_SPACE_GB_BEFORE}GB free"
|
|
||||||
echo " After: ${FREE_SPACE_GB_AFTER}GB free"
|
|
||||||
if (( $(echo "$FREED_GB > 100" | bc -l) )); then
|
|
||||||
echo " ✅ Successfully freed: ${FREED_GB}GB!"
|
|
||||||
elif (( $(echo "$FREED_GB > 0" | bc -l) )); then
|
|
||||||
echo " ✅ Freed: ${FREED_GB}GB"
|
|
||||||
else
|
|
||||||
echo " ⚠️ No space freed yet"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "=== If Still No Change ==="
|
|
||||||
echo ""
|
|
||||||
echo "The 351GB in System Data is likely:"
|
|
||||||
echo " 1. Purgeable space that macOS won't release until needed"
|
|
||||||
echo " 2. APFS snapshot overhead (the OS update snapshot)"
|
|
||||||
echo " 3. Reserved space for system operations"
|
|
||||||
echo ""
|
|
||||||
echo "Try these:"
|
|
||||||
echo ""
|
|
||||||
echo "1. **Create a large file to force purge**:"
|
|
||||||
echo " This forces macOS to release purgeable space:"
|
|
||||||
echo " dd if=/dev/zero of=~/test_large_file bs=1g count=50"
|
|
||||||
echo " (This creates a 50GB file, forcing purge)"
|
|
||||||
echo " Then delete it: rm ~/test_large_file"
|
|
||||||
echo ""
|
|
||||||
echo "2. **Use Activity Monitor**:"
|
|
||||||
echo " Open Activity Monitor → Disk tab"
|
|
||||||
echo " Look for 'Purgeable' space"
|
|
||||||
echo ""
|
|
||||||
echo "3. **Check Storage Management again**:"
|
|
||||||
echo " The System Data may show as 'Purgeable'"
|
|
||||||
echo " macOS will release it when space is actually needed"
|
|
||||||
echo ""
|
|
||||||
echo "4. **The space may already be available**:"
|
|
||||||
echo " Even though System Data shows 351GB, the space"
|
|
||||||
echo " may be purgeable and available when needed"
|
|
||||||
echo ""
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
# Apple Support Issue Summary
|
|
||||||
|
|
||||||
## Problem Description
|
|
||||||
|
|
||||||
**Main Issue:** Cannot free disk space to install macOS update due to OS update snapshot preserving all deleted/moved files.
|
|
||||||
|
|
||||||
## Symptoms
|
|
||||||
|
|
||||||
1. **System Data is 351GB** (should be ~20-30GB)
|
|
||||||
2. **Disk is 99.8% full** (only 800MB free out of 494GB)
|
|
||||||
3. **macOS update requires 17.64GB** but cannot free space
|
|
||||||
4. **Every file deletion/move makes System Data grow** instead of freeing space
|
|
||||||
|
|
||||||
## Root Cause
|
|
||||||
|
|
||||||
**OS Update Snapshot is blocking space recovery:**
|
|
||||||
- Snapshot name: `com.apple.os.update-C6AB179000F92C4C211177BC5C840A511D1AA2A227C324AA9C14FC599E9873`
|
|
||||||
- Status: **NOT purgeable**
|
|
||||||
- Note: "This snapshot limits the minimum size of APFS Container"
|
|
||||||
- The snapshot preserves ALL deleted/moved files, preventing space recovery
|
|
||||||
|
|
||||||
## What I've Tried (All Failed)
|
|
||||||
|
|
||||||
1. ✅ Moved files to NAS (Synology DS224plus) - Files moved but space not freed
|
|
||||||
2. ✅ Moved files to external drive - Files moved but space not freed
|
|
||||||
3. ✅ Cleaned caches (`~/Library/Caches`, `~/.cache`, npm cache) - No effect
|
|
||||||
4. ✅ Deleted local Time Machine snapshots - Ghost entry, can't delete
|
|
||||||
5. ✅ Attempted `tmutil deletelocalsnapshots` - Error: "Stale NFS file handle"
|
|
||||||
6. ✅ Attempted `tmutil thinlocalsnapshots` - No effect
|
|
||||||
7. ✅ Restarted Mac multiple times - No effect
|
|
||||||
8. ✅ Tried `softwareupdate --download --all` - Failed: "Not enough free disk space: 17.64 GB required"
|
|
||||||
|
|
||||||
## Current System Status
|
|
||||||
|
|
||||||
- **macOS Version:** macOS Tahoe (need to update to 26.2)
|
|
||||||
- **Disk:** 494.4GB APFS container, 99.8% full
|
|
||||||
- **Free Space:** 800MB (need 17.64GB for update)
|
|
||||||
- **System Data:** 351GB (should be ~20-30GB)
|
|
||||||
- **Snapshot:** OS update snapshot, NOT purgeable, cannot be deleted manually
|
|
||||||
|
|
||||||
## The Catch-22
|
|
||||||
|
|
||||||
- **Need:** 17.64GB free space to install macOS update
|
|
||||||
- **Problem:** Cannot free space because OS update snapshot preserves all deleted/moved files
|
|
||||||
- **Result:** Stuck - cannot update, cannot free space
|
|
||||||
|
|
||||||
## What I Need from Apple Support
|
|
||||||
|
|
||||||
1. **Tool to force-clear the OS update snapshot** (it's blocking space recovery)
|
|
||||||
2. **Alternative method to install macOS update** with limited space
|
|
||||||
3. **Recovery options** to break out of this catch-22 situation
|
|
||||||
4. **System-level intervention** to release the 351GB in System Data
|
|
||||||
|
|
||||||
## Technical Details
|
|
||||||
|
|
||||||
- **Snapshot UUID:** F63E39F3-D495-4586-88A4-A1406A7EF46A
|
|
||||||
- **Snapshot XID:** 6557111
|
|
||||||
- **Container:** disk3 (494.4GB)
|
|
||||||
- **Volume:** Macintosh HD (disk3s3)
|
|
||||||
- **Snapshot Disk:** disk3s3s1
|
|
||||||
|
|
||||||
## Files Are Safe
|
|
||||||
|
|
||||||
- Files have been moved to NAS and external drive
|
|
||||||
- Data is safe, but space cannot be recovered until snapshot is cleared
|
|
||||||
- The issue is purely about freeing space, not data loss
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Request:** Please provide system-level tools or recovery methods to clear the OS update snapshot so I can free space and install the macOS update.
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
# Cellular Data Proxy Solution
|
|
||||||
|
|
||||||
## The Problem
|
|
||||||
- ✅ Wi-Fi proxy works (configured in Wi-Fi settings)
|
|
||||||
- ❌ Cellular data proxy doesn't work (iOS doesn't allow HTTP proxy for cellular)
|
|
||||||
- ❌ Can't disable Tailscale VPN (proxy only listens on Tailscale IP: 100.70.115.1)
|
|
||||||
|
|
||||||
## Solution Options
|
|
||||||
|
|
||||||
### Solution 1: Use Shadowrocket VPN Mode (Recommended)
|
|
||||||
|
|
||||||
Shadowrocket's VPN mode works on **both Wi-Fi and cellular**, and can route through Tailscale's network.
|
|
||||||
|
|
||||||
**Setup:**
|
|
||||||
1. **Keep Tailscale VPN ON** (needed to reach 100.70.115.1)
|
|
||||||
2. In Shadowrocket:
|
|
||||||
- Go to **Home** tab
|
|
||||||
- Add server: `100.70.115.1:7890` (HTTP)
|
|
||||||
- Enable Shadowrocket VPN mode
|
|
||||||
3. Shadowrocket will:
|
|
||||||
- Intercept all traffic (Wi-Fi + cellular)
|
|
||||||
- Route through Tailscale network to reach proxy
|
|
||||||
- Forward to server2's proxy
|
|
||||||
|
|
||||||
**Wait - iOS only allows one VPN!** This won't work...
|
|
||||||
|
|
||||||
### Solution 2: Make Clash Listen on Public IP (Less Secure)
|
|
||||||
|
|
||||||
Configure Clash to also listen on the public IP, then use Shadowrocket VPN mode.
|
|
||||||
|
|
||||||
**Pros:** Works on cellular, Shadowrocket can use it
|
|
||||||
**Cons:** Less secure (exposed to public internet, but firewall should protect)
|
|
||||||
|
|
||||||
### Solution 3: Use Tailscale's Built-in Proxy Feature
|
|
||||||
|
|
||||||
Tailscale has a built-in proxy feature that might work better.
|
|
||||||
|
|
||||||
### Solution 4: Use Shadowrocket with Tailscale Subnet Router
|
|
||||||
|
|
||||||
Configure server2 as a Tailscale subnet router, then use Shadowrocket.
|
|
||||||
|
|
||||||
## Recommended: Solution 2 (Make Clash Listen on Public IP with Firewall)
|
|
||||||
|
|
||||||
Since you need cellular access, let's make Clash accessible via public IP but keep it secure with firewall rules.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Check Real Disk Space - Verify what's actually using space
|
|
||||||
# Sometimes the snapshot is a ghost but space is actually available
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Real Disk Space Analysis ==="
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Multiple methods to check space
|
|
||||||
echo "Method 1: df command:"
|
|
||||||
df -h / | tail -1
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "Method 2: diskutil info:"
|
|
||||||
diskutil info / | grep -E "Volume (Free|Used|Total) Space" | sed 's/^/ /'
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check if snapshot actually exists
|
|
||||||
echo "Method 3: APFS Snapshot Check:"
|
|
||||||
APFS_TM_SNAPS=$(diskutil apfs listSnapshots / 2>/dev/null | grep -i "timemachine" || echo "None")
|
|
||||||
if [ "$APFS_TM_SNAPS" = "None" ]; then
|
|
||||||
echo " ✅ No Time Machine snapshot in APFS (ghost entry only)"
|
|
||||||
else
|
|
||||||
echo " ⚠️ Found: $APFS_TM_SNAPS"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check Time Machine status
|
|
||||||
echo "Method 4: Time Machine Status:"
|
|
||||||
TM_RUNNING=$(tmutil status 2>/dev/null | grep "Running" | awk '{print $3}' | tr -d ';')
|
|
||||||
if [ "$TM_RUNNING" = "1" ]; then
|
|
||||||
echo " ⚠️ Time Machine is running (may be creating new snapshots)"
|
|
||||||
else
|
|
||||||
echo " ✅ Time Machine is not running"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Calculate actual space
|
|
||||||
FREE_KB=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_GB=$(echo "scale=2; $FREE_KB / 1024 / 1024" | bc)
|
|
||||||
|
|
||||||
echo "=== Summary ==="
|
|
||||||
echo " Current free space: ${FREE_GB}GB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
if (( $(echo "$FREE_GB < 5" | bc -l) )); then
|
|
||||||
echo "⚠️ Still low on space. The ghost snapshot entry is not the issue."
|
|
||||||
echo ""
|
|
||||||
echo "The real issue: Your disk is actually full (or nearly full)."
|
|
||||||
echo ""
|
|
||||||
echo "The 20GB from deleted files may have been:"
|
|
||||||
echo " 1. Used by Time Machine creating a new snapshot"
|
|
||||||
echo " 2. Used by other processes/files"
|
|
||||||
echo " 3. Actually freed but macOS hasn't updated the count yet"
|
|
||||||
echo ""
|
|
||||||
echo "Solutions:"
|
|
||||||
echo ""
|
|
||||||
echo "1. **Restart your Mac** - This will:"
|
|
||||||
echo " - Release any held snapshots"
|
|
||||||
echo " - Update disk space accounting"
|
|
||||||
echo " - Clear stuck processes"
|
|
||||||
echo ""
|
|
||||||
echo "2. Check what's really using space:"
|
|
||||||
echo " du -h -d 1 ~ | sort -hr | head -20"
|
|
||||||
echo ""
|
|
||||||
echo "3. Clean up large files:"
|
|
||||||
echo " - Downloads folder: $(du -sh ~/Downloads 2>/dev/null | awk '{print $1}')"
|
|
||||||
echo " - Library/Caches: $(du -sh ~/Library/Caches 2>/dev/null | awk '{print $1}')"
|
|
||||||
echo ""
|
|
||||||
echo "4. The ghost snapshot entry is harmless - ignore it."
|
|
||||||
echo " It will clear when Time Machine successfully backs up."
|
|
||||||
else
|
|
||||||
echo "✅ You have ${FREE_GB}GB free - this should be enough!"
|
|
||||||
echo ""
|
|
||||||
echo "The ghost snapshot entry can be ignored - it's not using space."
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
@@ -1,115 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Check Snapshot Size
|
|
||||||
# Determine how much space the snapshot is actually using
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Check Snapshot Size ==="
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Current disk space
|
|
||||||
FREE_SPACE=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB=$(echo "scale=2; $FREE_SPACE / 1024 / 1024" | bc)
|
|
||||||
USED_SPACE=$(df / | tail -1 | awk '{print $3}')
|
|
||||||
USED_SPACE_GB=$(echo "scale=2; $USED_SPACE / 1024 / 1024" | bc)
|
|
||||||
|
|
||||||
echo "📊 Current Disk Status:"
|
|
||||||
echo " Used: ${USED_SPACE_GB}GB"
|
|
||||||
echo " Free: ${FREE_SPACE_GB}GB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check if snapshot exists in APFS
|
|
||||||
echo "🔍 Checking if snapshot exists in APFS..."
|
|
||||||
APFS_CHECK=$(diskutil apfs listSnapshots / 2>/dev/null | grep -i "timemachine" || echo "NOT_FOUND")
|
|
||||||
if [ "$APFS_CHECK" = "NOT_FOUND" ]; then
|
|
||||||
echo " ❌ Snapshot NOT found in APFS"
|
|
||||||
echo " This means it's a GHOST ENTRY - not taking any space!"
|
|
||||||
echo ""
|
|
||||||
echo " The snapshot entry you see is just a stale database record."
|
|
||||||
echo " It's not actually consuming disk space."
|
|
||||||
echo ""
|
|
||||||
echo " ✅ Your space is already available!"
|
|
||||||
echo " The ghost entry will clear on restart."
|
|
||||||
else
|
|
||||||
echo " ✅ Snapshot found in APFS"
|
|
||||||
echo " $APFS_CHECK"
|
|
||||||
echo ""
|
|
||||||
echo " This snapshot IS taking up space."
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Try to get snapshot size
|
|
||||||
SNAPSHOT=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$" | head -1)
|
|
||||||
if [ -n "$SNAPSHOT" ]; then
|
|
||||||
echo "📸 Snapshot Details:"
|
|
||||||
echo " Name: $SNAPSHOT"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo " Attempting to calculate snapshot size..."
|
|
||||||
SNAP_DATE=$(echo "$SNAPSHOT" | sed 's/.*\.\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}\)\.backup/\1/')
|
|
||||||
|
|
||||||
# Try calculatedrift
|
|
||||||
DRIFT_OUTPUT=$(sudo tmutil calculatedrift "$SNAPSHOT" 2>&1 || echo "ERROR")
|
|
||||||
if echo "$DRIFT_OUTPUT" | grep -qi "size\|bytes\|GB\|MB"; then
|
|
||||||
echo " Size information:"
|
|
||||||
echo "$DRIFT_OUTPUT" | grep -i "size\|bytes\|GB\|MB" | head -5 | sed 's/^/ /'
|
|
||||||
else
|
|
||||||
echo " ⚠️ Could not calculate size (snapshot may be corrupted/stuck)"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Container vs Volume analysis
|
|
||||||
echo "📦 Container Analysis:"
|
|
||||||
CONTAINER_TOTAL=$(diskutil info / | grep 'Container Total' | awk '{print $4, $5}')
|
|
||||||
CONTAINER_FREE=$(diskutil info / | grep 'Container Free' | awk '{print $4, $5}')
|
|
||||||
VOLUME_USED=$(diskutil info / | grep 'Volume Used Space' | awk '{print $4, $5, $6}')
|
|
||||||
|
|
||||||
echo " Container Total: $CONTAINER_TOTAL"
|
|
||||||
echo " Container Free: $CONTAINER_FREE"
|
|
||||||
echo " Volume Used: $VOLUME_USED"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Calculate if there's unaccounted space
|
|
||||||
CONTAINER_TOTAL_GB=$(diskutil info / | grep 'Container Total' | awk '{print $3}' | tr -d 'GB')
|
|
||||||
CONTAINER_FREE_GB=$(diskutil info / | grep 'Container Free' | awk '{print $3}' | tr -d 'GB')
|
|
||||||
VOLUME_USED_GB=$(diskutil info / | grep 'Volume Used Space' | awk '{print $4}' | tr -d 'GB')
|
|
||||||
|
|
||||||
CONTAINER_USED_GB=$(echo "$CONTAINER_TOTAL_GB - $CONTAINER_FREE_GB" | bc)
|
|
||||||
DISCREPANCY=$(echo "$CONTAINER_USED_GB - $VOLUME_USED_GB" | bc)
|
|
||||||
|
|
||||||
echo " Container Used: ~${CONTAINER_USED_GB}GB"
|
|
||||||
echo " Volume Used: ~${VOLUME_USED_GB}GB"
|
|
||||||
if (( $(echo "$DISCREPANCY > 1" | bc -l) )); then
|
|
||||||
echo " ⚠️ Unaccounted: ~${DISCREPANCY}GB"
|
|
||||||
echo " This could be:"
|
|
||||||
echo " - APFS snapshots"
|
|
||||||
echo " - Other volumes"
|
|
||||||
echo " - Reserved space"
|
|
||||||
else
|
|
||||||
echo " ✅ Space accounting looks normal"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Summary
|
|
||||||
echo "=== Summary ==="
|
|
||||||
echo ""
|
|
||||||
if [ "$APFS_CHECK" = "NOT_FOUND" ]; then
|
|
||||||
echo "✅ The snapshot is a GHOST ENTRY - it's NOT taking any space!"
|
|
||||||
echo ""
|
|
||||||
echo " Your disk space is already available."
|
|
||||||
echo " The entry will clear on restart."
|
|
||||||
echo ""
|
|
||||||
echo " If 'System Data' is still growing when you delete files,"
|
|
||||||
echo " it's because Time Machine is creating NEW snapshots,"
|
|
||||||
echo " not because of this old ghost entry."
|
|
||||||
else
|
|
||||||
echo "⚠️ The snapshot IS in APFS and may be taking space."
|
|
||||||
echo ""
|
|
||||||
echo " To free the space, you need to:"
|
|
||||||
echo " 1. Remove Time Machine destination"
|
|
||||||
echo " 2. Restart your Mac"
|
|
||||||
echo " 3. The snapshot should be cleared"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Check Space After Unmounting Photo Volume
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Space Check After Unmounting Photo Volume ==="
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
FREE_SPACE=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB=$(echo "scale=2; $FREE_SPACE / 1024 / 1024" | bc)
|
|
||||||
CONTAINER_FREE=$(diskutil info / | grep 'Container Free' | awk '{print $4, $5}')
|
|
||||||
CONTAINER_USED=$(diskutil apfs list 2>/dev/null | grep "Capacity In Use" | awk '{print $6, $7}')
|
|
||||||
|
|
||||||
echo "📊 Current Status:"
|
|
||||||
echo " Free space: ${FREE_SPACE_GB}GB"
|
|
||||||
echo " Container free: $CONTAINER_FREE"
|
|
||||||
echo " Container used: $CONTAINER_USED"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check if photo is still mounted
|
|
||||||
if mount | grep -q photo; then
|
|
||||||
echo "⚠️ Photo volume is still mounted"
|
|
||||||
else
|
|
||||||
echo "✅ Photo volume is unmounted"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🔍 What's Actually Using Space:"
|
|
||||||
echo ""
|
|
||||||
echo "Top directories in /System/Volumes/Data:"
|
|
||||||
sudo du -h -d 1 /System/Volumes/Data 2>/dev/null | sort -hr | head -10 | awk '{printf " %8s %s\n", $1, $2}'
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "Your home directory:"
|
|
||||||
du -h -d 1 ~ 2>/dev/null | sort -hr | head -10 | awk '{printf " %8s %s\n", $1, $2}'
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "=== Analysis ==="
|
|
||||||
echo ""
|
|
||||||
if (( $(echo "$FREE_SPACE_GB < 5" | bc -l) )); then
|
|
||||||
echo "⚠️ Still critically low on space!"
|
|
||||||
echo ""
|
|
||||||
echo " The photo volume unmount didn't free space because:"
|
|
||||||
echo " - Those files were on the NAS (network), not local"
|
|
||||||
echo " - The 179GB was just the size of the network mount"
|
|
||||||
echo " - It wasn't actually consuming local disk space"
|
|
||||||
echo ""
|
|
||||||
echo " Your REAL space usage:"
|
|
||||||
echo " - Container: 492.9GB used (99.7% full)"
|
|
||||||
echo " - Your home: 130GB"
|
|
||||||
echo " - Other system files: ~360GB"
|
|
||||||
echo ""
|
|
||||||
echo " To free space, you need to:"
|
|
||||||
echo " 1. Clean Downloads: 8.7GB"
|
|
||||||
echo " 2. Clean Library/Caches: ~6GB"
|
|
||||||
echo " 3. Review Documents: 40GB (move large files to NAS)"
|
|
||||||
echo " 4. Review .ollama: 17GB (remove unused models)"
|
|
||||||
echo ""
|
|
||||||
else
|
|
||||||
echo "✅ You have ${FREE_SPACE_GB}GB free - this should be enough!"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
@@ -1,139 +0,0 @@
|
|||||||
# Clash Proxy Server Configuration
|
|
||||||
|
|
||||||
## Server Details
|
|
||||||
- **Server:** server2 (oracle-tokyo)
|
|
||||||
- **Tailscale IP:** 100.70.115.1
|
|
||||||
- **Status:** ✅ Running
|
|
||||||
|
|
||||||
## Proxy Endpoints
|
|
||||||
|
|
||||||
### HTTP Proxy
|
|
||||||
- **Type:** HTTP
|
|
||||||
- **Server:** 100.70.115.1
|
|
||||||
- **Port:** 7890
|
|
||||||
|
|
||||||
### SOCKS5 Proxy
|
|
||||||
- **Type:** SOCKS5
|
|
||||||
- **Server:** 100.70.115.1
|
|
||||||
- **Port:** 7891
|
|
||||||
|
|
||||||
### Mixed Port (Recommended)
|
|
||||||
- **Type:** HTTP/SOCKS5 (auto-detected)
|
|
||||||
- **Server:** 100.70.115.1
|
|
||||||
- **Port:** 7892
|
|
||||||
|
|
||||||
### Web Dashboard
|
|
||||||
- **URL:** http://100.70.115.1:9090/ui
|
|
||||||
- Use this to monitor traffic and manage settings
|
|
||||||
|
|
||||||
## Client Configuration
|
|
||||||
|
|
||||||
### For Clash Clients (Clash for Windows, ClashX, Clash Verge, etc.)
|
|
||||||
|
|
||||||
#### Option 1: Direct Proxy Configuration
|
|
||||||
In your Clash client settings, add a proxy:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
proxies:
|
|
||||||
- name: "server2-proxy"
|
|
||||||
type: http
|
|
||||||
server: 100.70.115.1
|
|
||||||
port: 7890
|
|
||||||
# Or use mixed port:
|
|
||||||
# port: 7892
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Option 2: Use as Upstream Proxy
|
|
||||||
If you want to route through server2:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
proxies:
|
|
||||||
- name: "server2"
|
|
||||||
type: http
|
|
||||||
server: 100.70.115.1
|
|
||||||
port: 7892
|
|
||||||
```
|
|
||||||
|
|
||||||
Then add it to your proxy groups:
|
|
||||||
```yaml
|
|
||||||
proxy-groups:
|
|
||||||
- name: "Proxy"
|
|
||||||
type: select
|
|
||||||
proxies:
|
|
||||||
- server2
|
|
||||||
- DIRECT
|
|
||||||
```
|
|
||||||
|
|
||||||
### For System-Wide Proxy (macOS/Windows)
|
|
||||||
|
|
||||||
#### macOS:
|
|
||||||
1. System Settings → Network → Advanced → Proxies
|
|
||||||
2. Check "Web Proxy (HTTP)" and "Secure Web Proxy (HTTPS)"
|
|
||||||
3. Server: 100.70.115.1
|
|
||||||
4. Port: 7890 (or 7892 for mixed)
|
|
||||||
|
|
||||||
#### Windows:
|
|
||||||
1. Settings → Network & Internet → Proxy
|
|
||||||
2. Manual proxy setup
|
|
||||||
3. Address: 100.70.115.1
|
|
||||||
4. Port: 7890
|
|
||||||
|
|
||||||
### For Mobile Apps (iOS/Android)
|
|
||||||
|
|
||||||
Most apps support HTTP/SOCKS5 proxy:
|
|
||||||
- **Type:** HTTP or SOCKS5
|
|
||||||
- **Host:** 100.70.115.1
|
|
||||||
- **Port:** 7890 (HTTP) or 7891 (SOCKS5) or 7892 (Mixed)
|
|
||||||
|
|
||||||
## Testing the Connection
|
|
||||||
|
|
||||||
### Test HTTP Proxy:
|
|
||||||
```bash
|
|
||||||
curl -x http://100.70.115.1:7890 https://api.ipify.org
|
|
||||||
```
|
|
||||||
|
|
||||||
### Test SOCKS5 Proxy:
|
|
||||||
```bash
|
|
||||||
curl --socks5 100.70.115.1:7891 https://api.ipify.org
|
|
||||||
```
|
|
||||||
|
|
||||||
### Check if proxy is working:
|
|
||||||
Visit http://100.70.115.1:9090/ui in your browser to see the Clash dashboard.
|
|
||||||
|
|
||||||
## Management Commands
|
|
||||||
|
|
||||||
### Check Status:
|
|
||||||
```bash
|
|
||||||
ssh server2 'sudo systemctl status clash-meta'
|
|
||||||
```
|
|
||||||
|
|
||||||
### View Logs:
|
|
||||||
```bash
|
|
||||||
ssh server2 'sudo journalctl -u clash-meta -f'
|
|
||||||
```
|
|
||||||
|
|
||||||
### Restart Service:
|
|
||||||
```bash
|
|
||||||
ssh server2 'sudo systemctl restart clash-meta'
|
|
||||||
```
|
|
||||||
|
|
||||||
### Stop Service:
|
|
||||||
```bash
|
|
||||||
ssh server2 'sudo systemctl stop clash-meta'
|
|
||||||
```
|
|
||||||
|
|
||||||
## Notes
|
|
||||||
|
|
||||||
- All traffic routed through server2 will use server2's internet connection
|
|
||||||
- The proxy is accessible only via Tailscale network (secure)
|
|
||||||
- No authentication required (protected by Tailscale)
|
|
||||||
- The proxy uses "direct" mode - all traffic goes directly through server2's connection
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
FROM node:20-slim
|
|
||||||
RUN apt-get update && apt-get install -y git openssh-client tmux && rm -rf /var/lib/apt/lists/*
|
|
||||||
RUN npm install -g @anthropic-ai/claude-code
|
|
||||||
WORKDIR /workspace
|
|
||||||
ENTRYPOINT ["tmux", "new-session", "-A", "-s", "main"]
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
services:
|
|
||||||
claude-dev:
|
|
||||||
build: .
|
|
||||||
image: claude-dev:latest
|
|
||||||
container_name: claude-dev
|
|
||||||
restart: unless-stopped
|
|
||||||
stdin_open: true
|
|
||||||
tty: true
|
|
||||||
environment:
|
|
||||||
- ANTHROPIC_BASE_URL=${ANTHROPIC_BASE_URL}
|
|
||||||
- ANTHROPIC_AUTH_TOKEN=${ANTHROPIC_AUTH_TOKEN}
|
|
||||||
- ANTHROPIC_API_KEY=${ANTHROPIC_AUTH_TOKEN}
|
|
||||||
volumes:
|
|
||||||
- /volume1/docker/claude-dev/workspace:/workspace
|
|
||||||
- /volume1/docker/claude-dev/claude-config:/root/.claude
|
|
||||||
logging:
|
|
||||||
driver: json-file
|
|
||||||
options:
|
|
||||||
max-size: "10m"
|
|
||||||
max-file: "3"
|
|
||||||
@@ -1,142 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Clean Time Machine System Files
|
|
||||||
# This script safely removes Time Machine files from system locations
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Time Machine System Files Cleanup ==="
|
|
||||||
echo ""
|
|
||||||
echo "⚠️ WARNING: This script will delete Time Machine system files."
|
|
||||||
echo " Make sure you understand what will be deleted."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check current free space
|
|
||||||
FREE_SPACE_BEFORE=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB_BEFORE=$(echo "scale=2; $FREE_SPACE_BEFORE / 1024 / 1024" | bc)
|
|
||||||
echo "Current free space: ${FREE_SPACE_GB_BEFORE}GB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Ask for confirmation
|
|
||||||
read -p "Do you want to proceed? This will delete Time Machine system files. (yes/no) " -r
|
|
||||||
echo ""
|
|
||||||
if [[ ! $REPLY =~ ^[Yy][Ee][Ss]$ ]]; then
|
|
||||||
echo "Cancelled."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "🧹 Cleaning Time Machine system files..."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
FREED_TOTAL=0
|
|
||||||
|
|
||||||
# 1. Delete local snapshots
|
|
||||||
echo "1. Deleting local snapshots..."
|
|
||||||
SNAPSHOTS=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$")
|
|
||||||
if [ -n "$SNAPSHOTS" ]; then
|
|
||||||
echo "$SNAPSHOTS" | while read snapshot; do
|
|
||||||
if [ -n "$snapshot" ]; then
|
|
||||||
echo " Deleting snapshot: $snapshot"
|
|
||||||
sudo tmutil deletelocalsnapshots "$snapshot" 2>/dev/null || {
|
|
||||||
echo " ⚠️ Could not delete $snapshot (may require different method)"
|
|
||||||
}
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
echo " ✓ Local snapshots deleted"
|
|
||||||
else
|
|
||||||
echo " ✓ No local snapshots to delete"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 2. Disable local snapshots temporarily (they'll recreate but this helps)
|
|
||||||
echo "2. Disabling local snapshots (to prevent immediate recreation)..."
|
|
||||||
sudo tmutil disablelocal 2>/dev/null || echo " ⚠️ Could not disable local snapshots"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 3. Clean MobileBackups (if they exist and are safe to remove)
|
|
||||||
echo "3. Checking MobileBackups..."
|
|
||||||
if [ -d "/.MobileBackups" ] || [ -d "/System/Volumes/Data/.MobileBackups" ]; then
|
|
||||||
echo " ⚠️ MobileBackups directory found."
|
|
||||||
echo " These are APFS snapshots. They're usually managed automatically."
|
|
||||||
echo " Deleting them manually can cause issues."
|
|
||||||
echo " Recommendation: Let macOS manage these automatically."
|
|
||||||
echo " They will be deleted when space is needed."
|
|
||||||
read -p " Do you want to try deleting MobileBackups? (yes/no) " -r
|
|
||||||
if [[ $REPLY =~ ^[Yy][Ee][Ss]$ ]]; then
|
|
||||||
if [ -d "/.MobileBackups" ]; then
|
|
||||||
echo " Attempting to delete /.MobileBackups..."
|
|
||||||
sudo rm -rf /.MobileBackups/* 2>/dev/null || echo " ⚠️ Could not delete (may be in use)"
|
|
||||||
fi
|
|
||||||
if [ -d "/System/Volumes/Data/.MobileBackups" ]; then
|
|
||||||
echo " Attempting to delete /System/Volumes/Data/.MobileBackups..."
|
|
||||||
sudo rm -rf /System/Volumes/Data/.MobileBackups/* 2>/dev/null || echo " ⚠️ Could not delete (may be in use)"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo " ✓ No MobileBackups directory found"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 4. Find and remove orphaned sparse bundles
|
|
||||||
echo "4. Searching for orphaned Time Machine sparse bundles..."
|
|
||||||
find /private/var -name "*.sparsebundle" -o -name "*.sparseimage" 2>/dev/null | while read bundle; do
|
|
||||||
if [ -e "$bundle" ]; then
|
|
||||||
SIZE=$(sudo du -sh "$bundle" 2>/dev/null | awk '{print $1}')
|
|
||||||
echo " Found: $bundle ($SIZE)"
|
|
||||||
read -p " Delete this bundle? (yes/no) " -r
|
|
||||||
if [[ $REPLY =~ ^[Yy][Ee][Ss]$ ]]; then
|
|
||||||
sudo rm -rf "$bundle" 2>/dev/null && echo " ✓ Deleted" || echo " ⚠️ Could not delete"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 5. Clean Time Machine logs (safe, will regenerate)
|
|
||||||
echo "5. Cleaning Time Machine logs..."
|
|
||||||
sudo rm -rf /private/var/log/com.apple.TimeMachine* 2>/dev/null || true
|
|
||||||
echo " ✓ Logs cleaned"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 6. Re-enable local snapshots (they're useful, just need space first)
|
|
||||||
echo "6. Re-enabling local snapshots..."
|
|
||||||
sudo tmutil enablelocal 2>/dev/null || echo " ⚠️ Could not re-enable (may already be enabled)"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check new free space
|
|
||||||
FREE_SPACE_AFTER=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB_AFTER=$(echo "scale=2; $FREE_SPACE_AFTER / 1024 / 1024" | bc)
|
|
||||||
FREED_GB=$(echo "scale=2; $FREE_SPACE_GB_AFTER - $FREE_SPACE_GB_BEFORE" | bc)
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "=== Results ==="
|
|
||||||
echo " Before: ${FREE_SPACE_GB_BEFORE}GB free"
|
|
||||||
echo " After: ${FREE_SPACE_GB_AFTER}GB free"
|
|
||||||
if (( $(echo "$FREED_GB > 0" | bc -l) )); then
|
|
||||||
echo " Freed: ${FREED_GB}GB"
|
|
||||||
else
|
|
||||||
echo " Freed: 0GB (files may be in use or protected)"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
if (( $(echo "$FREE_SPACE_GB_AFTER < 10" | bc -l) )); then
|
|
||||||
echo "⚠️ Still low on space. The 100GB+ may be in a protected location."
|
|
||||||
echo ""
|
|
||||||
echo "Next steps:"
|
|
||||||
echo "1. Check macOS Storage Management:"
|
|
||||||
echo " Apple Menu → About This Mac → Storage → Manage"
|
|
||||||
echo " Look for 'System Files' and see what's taking space"
|
|
||||||
echo ""
|
|
||||||
echo "2. The files may be APFS snapshots that need special handling:"
|
|
||||||
echo " sudo tmutil listlocalsnapshots /"
|
|
||||||
echo " # Then delete each one:"
|
|
||||||
echo " sudo tmutil deletelocalsnapshots <snapshot-name>"
|
|
||||||
echo ""
|
|
||||||
echo "3. Check for large files in system locations:"
|
|
||||||
echo " sudo du -h -d 1 /System/Volumes/Data | sort -hr | head -20"
|
|
||||||
echo ""
|
|
||||||
else
|
|
||||||
echo "✅ Good! You should have enough space for Time Machine now."
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Cleanup Ghost Time Machine Snapshot
|
|
||||||
# Sometimes snapshots appear in the list but don't actually exist or take space
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Cleanup Ghost Time Machine Snapshot ==="
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check current free space
|
|
||||||
FREE_SPACE=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB=$(echo "scale=2; $FREE_SPACE / 1024 / 1024" | bc)
|
|
||||||
echo "Current free space: ${FREE_SPACE_GB}GB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# List snapshots
|
|
||||||
SNAPSHOTS=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$")
|
|
||||||
if [ -z "$SNAPSHOTS" ]; then
|
|
||||||
echo "✅ No snapshots found - all clean!"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Found snapshot(s):"
|
|
||||||
echo "$SNAPSHOTS" | sed 's/^/ - /'
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# The snapshot might be a ghost entry. Let's try several methods:
|
|
||||||
|
|
||||||
echo "Attempting cleanup methods..."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Method 1: Try deleting with date format
|
|
||||||
echo "Method 1: Delete by date..."
|
|
||||||
echo "$SNAPSHOTS" | while read snapshot; do
|
|
||||||
if [ -n "$snapshot" ]; then
|
|
||||||
# Extract date: com.apple.TimeMachine.2025-12-31-101235.backup -> 2025-12-31-101235
|
|
||||||
SNAP_DATE=$(echo "$snapshot" | sed 's/.*\.\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}\)\.backup/\1/')
|
|
||||||
if [ -n "$SNAP_DATE" ]; then
|
|
||||||
echo " Trying: sudo tmutil deletelocalsnapshots $SNAP_DATE"
|
|
||||||
if sudo tmutil deletelocalsnapshots "$SNAP_DATE" 2>/dev/null; then
|
|
||||||
echo " ✅ Success!"
|
|
||||||
else
|
|
||||||
echo " ⚠️ Failed (may be ghost entry)"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Method 2: Thin all snapshots (aggressive)
|
|
||||||
echo "Method 2: Aggressive thinning..."
|
|
||||||
sudo tmutil thinlocalsnapshots / 1000000000 1 2>&1 || true
|
|
||||||
echo " ✓ Thinning completed"
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Method 3: Check if it's actually taking space
|
|
||||||
echo "Method 3: Checking if snapshot actually exists..."
|
|
||||||
APFS_SNAPSHOTS=$(diskutil apfs listSnapshots / 2>/dev/null | grep -i "timemachine" || echo "")
|
|
||||||
if [ -z "$APFS_SNAPSHOTS" ]; then
|
|
||||||
echo " ℹ️ Snapshot not found in APFS snapshot list"
|
|
||||||
echo " This confirms it's likely a ghost entry in Time Machine's database"
|
|
||||||
echo ""
|
|
||||||
echo " The snapshot entry may persist in Time Machine's database but:"
|
|
||||||
echo " - It's not taking up space (space was already freed)"
|
|
||||||
echo " - It will likely clear when Time Machine successfully backs up"
|
|
||||||
echo " - Or it may clear on the next macOS update/restart"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Final check
|
|
||||||
sleep 2
|
|
||||||
REMAINING=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$" | wc -l | tr -d ' ')
|
|
||||||
|
|
||||||
if [ "$REMAINING" -gt 0 ]; then
|
|
||||||
echo "⚠️ Snapshot still listed, but this is likely a ghost entry."
|
|
||||||
echo ""
|
|
||||||
echo "✅ Good news: Your space was already freed (${FREE_SPACE_GB}GB free)!"
|
|
||||||
echo ""
|
|
||||||
echo "The ghost entry should clear when:"
|
|
||||||
echo " 1. Time Machine successfully completes a backup"
|
|
||||||
echo " 2. macOS updates"
|
|
||||||
echo " 3. Or it may persist but won't cause issues"
|
|
||||||
echo ""
|
|
||||||
echo "You can safely ignore it - it's not taking up space."
|
|
||||||
else
|
|
||||||
echo "✅ Snapshot successfully removed!"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
@@ -102,7 +102,7 @@ async def monitor_containers():
|
|||||||
)
|
)
|
||||||
previous_states[c.id] = current_status
|
previous_states[c.id] = current_status
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error in container monitor: {e}")
|
logging.getLogger(__name__).error("Error in container monitor: %s", e)
|
||||||
|
|
||||||
await asyncio.sleep(60)
|
await asyncio.sleep(60)
|
||||||
|
|
||||||
|
|||||||
@@ -11,11 +11,13 @@ from slowapi.util import get_remote_address
|
|||||||
import jwt
|
import jwt
|
||||||
import config
|
import config
|
||||||
import auth
|
import auth
|
||||||
|
import logging
|
||||||
import pyotp
|
import pyotp
|
||||||
from webauthn import generate_registration_options, verify_registration_response, generate_authentication_options, verify_authentication_response
|
from webauthn import generate_registration_options, verify_registration_response, generate_authentication_options, verify_authentication_response
|
||||||
from webauthn.helpers.structs import PublicKeyCredentialDescriptor, UserVerificationRequirement
|
from webauthn.helpers.structs import PublicKeyCredentialDescriptor, UserVerificationRequirement
|
||||||
from webauthn.helpers import bytes_to_base64url, base64url_to_bytes, options_to_json
|
from webauthn.helpers import bytes_to_base64url, base64url_to_bytes, options_to_json
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
limiter = Limiter(key_func=get_remote_address)
|
limiter = Limiter(key_func=get_remote_address)
|
||||||
|
|
||||||
@@ -43,9 +45,9 @@ class Verify2FARequest(BaseModel):
|
|||||||
code: str
|
code: str
|
||||||
|
|
||||||
async def send_failed_login_alert(ip_address: str, username: str, reason: str):
|
async def send_failed_login_alert(ip_address: str, username: str, reason: str):
|
||||||
print(f"Triggering Telegram alert for {username} from {ip_address}: {reason}", flush=True)
|
logger.info("Triggering Telegram alert for %s from %s: %s", username, ip_address, reason)
|
||||||
if not config.TELEGRAM_BOT_TOKEN or not config.TELEGRAM_CHAT_ID:
|
if not config.TELEGRAM_BOT_TOKEN or not config.TELEGRAM_CHAT_ID:
|
||||||
print("Skipping Telegram alert: missing config", flush=True)
|
logger.warning("Skipping Telegram alert: missing config")
|
||||||
return
|
return
|
||||||
msg = f"🚨 *Dashboard Security Alert* 🚨\nFailed login attempt detected.\n\n👤 User: `{username}`\n🌐 IP: `{ip_address}`\n❌ Reason: {reason}"
|
msg = f"🚨 *Dashboard Security Alert* 🚨\nFailed login attempt detected.\n\n👤 User: `{username}`\n🌐 IP: `{ip_address}`\n❌ Reason: {reason}"
|
||||||
try:
|
try:
|
||||||
@@ -59,9 +61,9 @@ async def send_failed_login_alert(ip_address: str, username: str, reason: str):
|
|||||||
data={"chat_id": config.TELEGRAM_CHAT_ID, "text": msg, "parse_mode": "Markdown"},
|
data={"chat_id": config.TELEGRAM_CHAT_ID, "text": msg, "parse_mode": "Markdown"},
|
||||||
timeout=10.0
|
timeout=10.0
|
||||||
)
|
)
|
||||||
print(f"Telegram alert sent, status: {res.status_code}", flush=True)
|
logger.info("Telegram alert sent, status: %s", res.status_code)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Failed to send Telegram alert: {e}", flush=True)
|
logger.warning("Failed to send Telegram alert: %s", e)
|
||||||
|
|
||||||
@router.post("/login", response_model=Token)
|
@router.post("/login", response_model=Token)
|
||||||
@limiter.limit("5/minute")
|
@limiter.limit("5/minute")
|
||||||
|
|||||||
@@ -1,67 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# EnConvo Settings Crash Debug Script
|
|
||||||
# Run this script, then click Settings in EnConvo to capture the crash
|
|
||||||
|
|
||||||
echo "=== EnConvo Settings Crash Debugger ==="
|
|
||||||
echo ""
|
|
||||||
echo "This script will:"
|
|
||||||
echo "1. Monitor crash logs"
|
|
||||||
echo "2. Capture Console output"
|
|
||||||
echo "3. Show process info"
|
|
||||||
echo ""
|
|
||||||
echo "Press Ctrl+C to stop monitoring"
|
|
||||||
echo ""
|
|
||||||
echo "Starting monitoring... (Now click Settings in EnConvo)"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Get the current time for filtering logs
|
|
||||||
START_TIME=$(date +"%Y-%m-%d %H:%M:%S")
|
|
||||||
|
|
||||||
# Function to check for crash reports
|
|
||||||
check_crashes() {
|
|
||||||
echo "=== Checking for Crash Reports ==="
|
|
||||||
CRASH_DIR="$HOME/Library/Logs/DiagnosticReports"
|
|
||||||
if [ -d "$CRASH_DIR" ]; then
|
|
||||||
echo "Recent EnConvo crash reports:"
|
|
||||||
find "$CRASH_DIR" -name "*EnConvo*" -type f -mmin -5 2>/dev/null | head -5
|
|
||||||
echo ""
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Function to monitor Console logs
|
|
||||||
monitor_console() {
|
|
||||||
echo "=== Monitoring Console Logs (last 20 lines) ==="
|
|
||||||
log show --predicate 'process == "EnConvo"' --last 1m --style compact 2>/dev/null | tail -20
|
|
||||||
echo ""
|
|
||||||
}
|
|
||||||
|
|
||||||
# Function to check running processes
|
|
||||||
check_processes() {
|
|
||||||
echo "=== EnConvo Processes ==="
|
|
||||||
ps aux | grep -i enconvo | grep -v grep
|
|
||||||
echo ""
|
|
||||||
}
|
|
||||||
|
|
||||||
# Run initial checks
|
|
||||||
check_processes
|
|
||||||
|
|
||||||
# Monitor in a loop
|
|
||||||
while true; do
|
|
||||||
sleep 2
|
|
||||||
check_crashes
|
|
||||||
monitor_console
|
|
||||||
check_processes
|
|
||||||
echo "--- Waiting for crash (click Settings now if you haven't) ---"
|
|
||||||
echo ""
|
|
||||||
done
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Deep Space Analysis - Find where the 20GB actually went
|
|
||||||
# When deleted files don't free space even after restart
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Deep Space Analysis ==="
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Container vs Volume space
|
|
||||||
echo "📊 Container vs Volume Space:"
|
|
||||||
echo " Container Total: $(diskutil info / | grep 'Container Total' | awk '{print $4, $5}')"
|
|
||||||
echo " Container Free: $(diskutil info / | grep 'Container Free' | awk '{print $4, $5}')"
|
|
||||||
echo " Volume Used: $(diskutil info / | grep 'Volume Used Space' | awk '{print $4, $5, $6}')"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Calculate discrepancy
|
|
||||||
CONTAINER_TOTAL=$(diskutil info / | grep 'Container Total' | awk '{print $3}' | tr -d 'GB')
|
|
||||||
CONTAINER_FREE=$(diskutil info / | grep 'Container Free' | awk '{print $3}' | tr -d 'GB')
|
|
||||||
VOLUME_USED=$(diskutil info / | grep 'Volume Used Space' | awk '{print $4}' | tr -d 'GB')
|
|
||||||
|
|
||||||
CONTAINER_USED=$(echo "$CONTAINER_TOTAL - $CONTAINER_FREE" | bc)
|
|
||||||
DISCREPANCY=$(echo "$CONTAINER_USED - $VOLUME_USED" | bc)
|
|
||||||
|
|
||||||
echo " Container Used: ~${CONTAINER_USED}GB"
|
|
||||||
echo " Volume Used: ~${VOLUME_USED}GB"
|
|
||||||
if (( $(echo "$DISCREPANCY > 5" | bc -l) )); then
|
|
||||||
echo " ⚠️ Discrepancy: ~${DISCREPANCY}GB unaccounted for!"
|
|
||||||
echo " This space may be in:"
|
|
||||||
echo " - Other APFS volumes"
|
|
||||||
echo " - APFS snapshots"
|
|
||||||
echo " - Reserved space"
|
|
||||||
echo " - System files"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check all APFS volumes
|
|
||||||
echo "📦 APFS Volumes:"
|
|
||||||
diskutil apfs list 2>/dev/null | grep -E "Volume Name|Used Space|Free Space" | head -20 | sed 's/^/ /'
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check snapshots
|
|
||||||
echo "📸 APFS Snapshots:"
|
|
||||||
SNAP_COUNT=$(diskutil apfs listSnapshots / 2>/dev/null | grep -c "Name:" || echo "0")
|
|
||||||
echo " Found $SNAP_COUNT snapshot(s)"
|
|
||||||
if [ "$SNAP_COUNT" -gt 0 ]; then
|
|
||||||
diskutil apfs listSnapshots / 2>/dev/null | grep -E "Name|Purgeable" | head -6 | sed 's/^/ /'
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check for large directories that might have been missed
|
|
||||||
echo "🔍 Large Directories Check:"
|
|
||||||
echo " Home directory: $(du -sh ~ 2>/dev/null | awk '{print $1}')"
|
|
||||||
echo " Documents: $(du -sh ~/Documents 2>/dev/null | awk '{print $1}')"
|
|
||||||
echo " Library: $(du -sh ~/Library 2>/dev/null | awk '{print $1}')"
|
|
||||||
echo " Downloads: $(du -sh ~/Downloads 2>/dev/null | awk '{print $1}')"
|
|
||||||
echo " Movies: $(du -sh ~/Movies 2>/dev/null | awk '{print $1}')"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check if files were actually deleted
|
|
||||||
echo "❓ Verification:"
|
|
||||||
echo " You mentioned deleting 20GB from Movies/Videos folder"
|
|
||||||
echo " Current Movies folder: $(du -sh ~/Movies 2>/dev/null | awk '{print $1}')"
|
|
||||||
echo ""
|
|
||||||
echo " Questions:"
|
|
||||||
echo " 1. Did you delete from ~/Movies or another location?"
|
|
||||||
echo " 2. Did you empty Trash after deleting?"
|
|
||||||
echo " 3. Are the files still in Trash?"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check trash
|
|
||||||
TRASH_SIZE=$(du -sh ~/.Trash 2>/dev/null | awk '{print $1}' || echo "0")
|
|
||||||
echo " Trash size: $TRASH_SIZE"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Summary
|
|
||||||
echo "=== Analysis ==="
|
|
||||||
echo ""
|
|
||||||
if (( $(echo "$DISCREPANCY > 15" | bc -l) )); then
|
|
||||||
echo "⚠️ Found ${DISCREPANCY}GB+ unaccounted space in container!"
|
|
||||||
echo ""
|
|
||||||
echo " This suggests:"
|
|
||||||
echo " 1. Files may not have been actually deleted"
|
|
||||||
echo " 2. Space is in another APFS volume"
|
|
||||||
echo " 3. APFS snapshots are holding space"
|
|
||||||
echo " 4. System reserved space"
|
|
||||||
echo ""
|
|
||||||
echo " Next steps:"
|
|
||||||
echo " 1. Verify files were actually deleted (not just moved to Trash)"
|
|
||||||
echo " 2. Empty Trash: rm -rf ~/.Trash/*"
|
|
||||||
echo " 3. Check other volumes: diskutil apfs list"
|
|
||||||
echo " 4. Check for large files: find ~ -size +1G -type f 2>/dev/null"
|
|
||||||
echo ""
|
|
||||||
else
|
|
||||||
echo " Space accounting looks normal."
|
|
||||||
echo " The 20GB may have been:"
|
|
||||||
echo " - Used by other files growing"
|
|
||||||
echo " - Actually still present (not deleted)"
|
|
||||||
echo " - In Trash (not emptied)"
|
|
||||||
echo ""
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Delete Local Snapshot to Free Space
|
|
||||||
# Since files are on NAS, it's safe to remove the snapshot
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Delete Local Snapshot to Free Space ==="
|
|
||||||
echo ""
|
|
||||||
echo "Since your files are safely backed up on NAS, we can delete"
|
|
||||||
echo "the local snapshot to free up space."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
FREE_SPACE_BEFORE=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB_BEFORE=$(echo "scale=2; $FREE_SPACE_BEFORE / 1024 / 1024" | bc)
|
|
||||||
echo "Current free space: ${FREE_SPACE_GB_BEFORE}GB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check snapshot
|
|
||||||
SNAPSHOT=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$" | head -1)
|
|
||||||
if [ -z "$SNAPSHOT" ]; then
|
|
||||||
echo "✅ No snapshot found - you're all set!"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Found snapshot: $SNAPSHOT"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Extract date
|
|
||||||
SNAP_DATE=$(echo "$SNAPSHOT" | sed 's/.*\.\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}\)\.backup/\1/')
|
|
||||||
|
|
||||||
if [ -z "$SNAP_DATE" ]; then
|
|
||||||
echo "⚠️ Could not parse snapshot date"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Attempting to delete snapshot: $SNAP_DATE"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Try to delete
|
|
||||||
if sudo tmutil deletelocalsnapshots "$SNAP_DATE" 2>/dev/null; then
|
|
||||||
echo "✅ Successfully deleted snapshot!"
|
|
||||||
echo ""
|
|
||||||
echo "⏳ Waiting for space to be released..."
|
|
||||||
sleep 5
|
|
||||||
|
|
||||||
FREE_SPACE_AFTER=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB_AFTER=$(echo "scale=2; $FREE_SPACE_AFTER / 1024 / 1024" | bc)
|
|
||||||
FREED_GB=$(echo "scale=2; $FREE_SPACE_GB_AFTER - $FREE_SPACE_GB_BEFORE" | bc)
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "=== Results ==="
|
|
||||||
echo " Before: ${FREE_SPACE_GB_BEFORE}GB free"
|
|
||||||
echo " After: ${FREE_SPACE_GB_AFTER}GB free"
|
|
||||||
if (( $(echo "$FREED_GB > 0" | bc -l) )); then
|
|
||||||
echo " ✅ Freed: ${FREED_GB}GB"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "⚠️ Could not delete snapshot (Stale NFS file handle error)"
|
|
||||||
echo ""
|
|
||||||
echo "This is a known issue. The snapshot is stuck because:"
|
|
||||||
echo " - Time Machine had a stale connection to NAS"
|
|
||||||
echo " - The snapshot reference is corrupted"
|
|
||||||
echo ""
|
|
||||||
echo "=== Solutions ==="
|
|
||||||
echo ""
|
|
||||||
echo "Option 1: Restart your Mac (Recommended)"
|
|
||||||
echo " This will release the stuck snapshot and free the space."
|
|
||||||
echo " After restart, the snapshot should be gone."
|
|
||||||
echo ""
|
|
||||||
echo "Option 2: Wait for macOS to auto-clean"
|
|
||||||
echo " macOS will eventually clean up stuck snapshots, but this"
|
|
||||||
echo " can take hours or days."
|
|
||||||
echo ""
|
|
||||||
echo "The good news: The snapshot is a GHOST ENTRY (not in APFS)."
|
|
||||||
echo "This means the space may already be available - the entry"
|
|
||||||
echo "is just a stale database record that will clear on restart."
|
|
||||||
echo ""
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Diagnose Synology USB Copy Issue
|
|
||||||
# Connects to NAS and checks USB device status
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Synology USB Copy Diagnosis ==="
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check if nas alias works
|
|
||||||
if ! command -v nas &> /dev/null; then
|
|
||||||
echo "⚠️ 'nas' alias not found. Using SSH directly."
|
|
||||||
echo " Please provide: ssh user@nas-ip"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "🔍 Checking USB device status on NAS..."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "1. USB Devices Connected:"
|
|
||||||
nas "lsusb 2>/dev/null || echo 'lsusb not available, checking dmesg...' && dmesg | grep -i usb | tail -5" || echo " ⚠️ Could not check USB devices"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "2. USB Mount Points:"
|
|
||||||
nas "mount | grep -i usb || echo ' No USB devices mounted'" || echo " ⚠️ Could not check mounts"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "3. USB Volumes:"
|
|
||||||
nas "ls -la /volumeUSB*/ 2>/dev/null || echo ' No /volumeUSB* directories found'" || echo " ⚠️ Could not check USB volumes"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "4. Disk Partitions:"
|
|
||||||
nas "cat /proc/partitions | grep -v '^major' | head -10" || echo " ⚠️ Could not check partitions"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "5. Disk Usage (USB devices):"
|
|
||||||
nas "df -h | grep -i usb || echo ' No USB devices in df output'" || echo " ⚠️ Could not check disk usage"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "6. USB Copy Service Status:"
|
|
||||||
nas "synoservice --status pkgctl-USB-Copy 2>/dev/null || echo ' Could not check USB Copy service status'" || echo " ⚠️ Could not check service"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "7. USB Copy Configuration:"
|
|
||||||
nas "cat /usr/syno/etc/packages/USB-Copy/usbcopy.conf 2>/dev/null | head -20 || echo ' Could not read USB Copy config'" || echo " ⚠️ Could not read config"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "8. Check for USB devices in /dev:"
|
|
||||||
nas "ls -la /dev/sd* /dev/hd* 2>/dev/null | head -10 || echo ' No USB block devices found'" || echo " ⚠️ Could not check devices"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "=== Diagnosis Summary ==="
|
|
||||||
echo ""
|
|
||||||
echo "Common issues to check:"
|
|
||||||
echo ""
|
|
||||||
echo "1. If no USB devices found:"
|
|
||||||
echo " - USB device not connected to front port"
|
|
||||||
echo " - USB device not recognized by Synology"
|
|
||||||
echo " - Try different USB device"
|
|
||||||
echo ""
|
|
||||||
echo "2. If USB device mounted but USB Copy shows 'Unavailable':"
|
|
||||||
echo " - USB device mounted as shared folder"
|
|
||||||
echo " - Another task using the USB device"
|
|
||||||
echo " - Need to unmount from other uses"
|
|
||||||
echo ""
|
|
||||||
echo "3. If USB Copy service not running:"
|
|
||||||
echo " - Package Center → USB Copy → Start"
|
|
||||||
echo ""
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Emergency Free Space - When Time Machine is stuck and consuming space
|
|
||||||
# This script provides the quickest way to free space
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Emergency Free Space Fix ==="
|
|
||||||
echo ""
|
|
||||||
echo "Time Machine is stuck and holding your deleted file space."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
FREE_SPACE_BEFORE=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB_BEFORE=$(echo "scale=2; $FREE_SPACE_BEFORE / 1024 / 1024" | bc)
|
|
||||||
echo "Current free space: ${FREE_SPACE_GB_BEFORE}GB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🔧 Solution: Remove Time Machine destination to free the stuck snapshot"
|
|
||||||
echo ""
|
|
||||||
echo "The snapshot is stuck because Time Machine can't connect to your NAS."
|
|
||||||
echo "Removing the destination will allow the snapshot to be deleted."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
read -p "Have you removed the Time Machine destination in System Settings? (y/n) " -n 1 -r
|
|
||||||
echo ""
|
|
||||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
||||||
echo ""
|
|
||||||
echo "Please do this now:"
|
|
||||||
echo "1. Open System Settings → General → Time Machine"
|
|
||||||
echo "2. Click the '-' button to remove the backup disk"
|
|
||||||
echo "3. Confirm removal"
|
|
||||||
echo ""
|
|
||||||
echo "Then run this script again."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "⏳ Waiting for Time Machine to fully disconnect..."
|
|
||||||
sleep 5
|
|
||||||
|
|
||||||
# Kill any remaining backup processes
|
|
||||||
echo "🛑 Stopping any remaining Time Machine processes..."
|
|
||||||
sudo killall backupd 2>/dev/null || true
|
|
||||||
sleep 2
|
|
||||||
|
|
||||||
# Try to delete the snapshot now
|
|
||||||
echo ""
|
|
||||||
echo "🗑️ Attempting to delete stuck snapshot..."
|
|
||||||
SNAPSHOTS=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$")
|
|
||||||
if [ -n "$SNAPSHOTS" ]; then
|
|
||||||
echo "$SNAPSHOTS" | while read snapshot; do
|
|
||||||
if [ -n "$snapshot" ]; then
|
|
||||||
SNAP_DATE=$(echo "$snapshot" | sed 's/.*\.\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}\)\.backup/\1/')
|
|
||||||
if [ -n "$SNAP_DATE" ]; then
|
|
||||||
echo " Deleting: $snapshot"
|
|
||||||
if sudo tmutil deletelocalsnapshots "$SNAP_DATE" 2>/dev/null; then
|
|
||||||
echo " ✅ Successfully deleted!"
|
|
||||||
else
|
|
||||||
echo " ⚠️ Still stuck. Try restarting your Mac."
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
else
|
|
||||||
echo " ✅ No snapshots found"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "📊 Checking results..."
|
|
||||||
sleep 3
|
|
||||||
|
|
||||||
FREE_SPACE_AFTER=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB_AFTER=$(echo "scale=2; $FREE_SPACE_AFTER / 1024 / 1024" | bc)
|
|
||||||
FREED_GB=$(echo "scale=2; $FREE_SPACE_GB_AFTER - $FREE_SPACE_GB_BEFORE" | bc)
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "=== Results ==="
|
|
||||||
echo " Before: ${FREE_SPACE_GB_BEFORE}GB free"
|
|
||||||
echo " After: ${FREE_SPACE_GB_AFTER}GB free"
|
|
||||||
if (( $(echo "$FREED_GB > 15" | bc -l) )); then
|
|
||||||
echo " ✅ Successfully freed: ${FREED_GB}GB"
|
|
||||||
echo ""
|
|
||||||
echo " Your 20GB from deleted files should now be available!"
|
|
||||||
elif (( $(echo "$FREED_GB > 0" | bc -l) )); then
|
|
||||||
echo " ✅ Freed: ${FREED_GB}GB"
|
|
||||||
echo " (May need restart to free remaining space)"
|
|
||||||
else
|
|
||||||
echo " ⚠️ Space not freed yet"
|
|
||||||
echo ""
|
|
||||||
echo " Try restarting your Mac - this often releases stuck snapshots."
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "=== Next Steps ==="
|
|
||||||
echo ""
|
|
||||||
echo "1. After space is freed, fix Time Machine connection:"
|
|
||||||
echo " See: time_machine_troubleshooting.md"
|
|
||||||
echo ""
|
|
||||||
echo "2. Common fixes for NAS connection:"
|
|
||||||
echo " - Clear credentials: Keychain Access → search 'DS224plus' → delete"
|
|
||||||
echo " - Re-add Time Machine: System Settings → Time Machine → Add Backup Disk"
|
|
||||||
echo ""
|
|
||||||
echo "3. Once connection is fixed, Time Machine will work properly."
|
|
||||||
echo ""
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Emergency Options - When Update Can't Download
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Emergency Options ==="
|
|
||||||
echo ""
|
|
||||||
echo "Update download failed: Need 17.64GB, have less."
|
|
||||||
echo "You're in a catch-22 situation."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
FREE_SPACE=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB=$(echo "scale=2; $FREE_SPACE / 1024 / 1024" | bc)
|
|
||||||
echo "Current free space: ${FREE_SPACE_GB}GB"
|
|
||||||
echo "Needed: 17.64GB"
|
|
||||||
echo "Shortfall: ~$(echo "17.64 - $FREE_SPACE_GB" | bc)GB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🔧 OPTIONS:"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "1. **Use External Drive** (BEST OPTION)"
|
|
||||||
echo ""
|
|
||||||
echo " If you have an external USB drive:"
|
|
||||||
echo " a) Connect it"
|
|
||||||
echo " b) Move large files there (not NAS - external drive):"
|
|
||||||
echo " - Downloads (8.7GB)"
|
|
||||||
echo " - .ollama (17GB)"
|
|
||||||
echo " - .local (18GB)"
|
|
||||||
echo " c) Install macOS update"
|
|
||||||
echo " d) After update clears snapshot, move files back"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "2. **Contact Apple Support** (RECOMMENDED)"
|
|
||||||
echo ""
|
|
||||||
echo " Phone: 1-800-275-2273"
|
|
||||||
echo " Explain: 'OS update snapshot preventing space recovery'"
|
|
||||||
echo " They may:"
|
|
||||||
echo " - Have tools to force-clear snapshot"
|
|
||||||
echo " - Help with update process"
|
|
||||||
echo " - Provide other solutions"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "3. **Try System Settings Update** (Sometimes works differently)"
|
|
||||||
echo ""
|
|
||||||
echo " System Settings → General → Software Update"
|
|
||||||
echo " Click 'Update Now'"
|
|
||||||
echo " Sometimes GUI works when command line doesn't"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "4. **Check for External Storage**"
|
|
||||||
echo ""
|
|
||||||
echo " Do you have:"
|
|
||||||
echo " - USB drive?"
|
|
||||||
echo " - SD card?"
|
|
||||||
echo " - Another Mac you can network to?"
|
|
||||||
echo " - Cloud storage (iCloud, Dropbox, etc.)?"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "5. **Last Resort: Clean Install** (Loses data, not recommended)"
|
|
||||||
echo ""
|
|
||||||
echo " ⚠️ Only if you have everything backed up"
|
|
||||||
echo " - Create bootable installer"
|
|
||||||
echo " - Fresh install macOS"
|
|
||||||
echo " - Restore from Time Machine"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "=== What You CAN Do Right Now ==="
|
|
||||||
echo ""
|
|
||||||
echo "Even though space isn't freed, your files ARE safe on NAS."
|
|
||||||
echo ""
|
|
||||||
echo "The space WILL be freed after updating macOS."
|
|
||||||
echo ""
|
|
||||||
echo "The blocker is: You need space to update, but can't free space"
|
|
||||||
echo "because the snapshot preserves everything."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🎯 IMMEDIATE ACTION:"
|
|
||||||
echo ""
|
|
||||||
echo "1. Check if you have external drive"
|
|
||||||
echo "2. If yes: Use it to temporarily move files"
|
|
||||||
echo "3. If no: Contact Apple Support (1-800-275-2273)"
|
|
||||||
echo ""
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
EnConvo Settings Crash Report
|
|
||||||
==============================
|
|
||||||
|
|
||||||
Environment:
|
|
||||||
- Device: MacBook Air (M1)
|
|
||||||
- macOS Version: Ventura 13.x
|
|
||||||
- App Version: 2.2.22
|
|
||||||
- Issue: App crashes when clicking Settings sidebar button
|
|
||||||
|
|
||||||
Error Output:
|
|
||||||
-------------
|
|
||||||
PostHog -> Error not initialized due to missing API key or host
|
|
||||||
|
|
||||||
[SwiftCPUDetect] Detected CPU type number: 16777228
|
|
||||||
[SwiftCPUDetect] Detected CPU subtype number: 2
|
|
||||||
[SwiftCPUDetect] Detected CPU family number: 458787763
|
|
||||||
[SwiftCPUDetect] Detected cpu architecture of the current process is: arm64
|
|
||||||
|
|
||||||
WARNING: The sun_len field of a sockaddr_un structure passed to CFSocketSetAddress was not set correctly using the SUN_LEN macro.
|
|
||||||
|
|
||||||
(node) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
|
|
||||||
|
|
||||||
zsh: trace trap /Applications/EnConvo.app/Contents/MacOS/EnConvo
|
|
||||||
|
|
||||||
Crash Type:
|
|
||||||
-----------
|
|
||||||
"trace trap" indicates the app received a SIGTRAP signal, typically from:
|
|
||||||
- Breakpoint hit
|
|
||||||
- Assertion failure
|
|
||||||
- Debugger attachment
|
|
||||||
- Memory access violation
|
|
||||||
|
|
||||||
Note: This works fine on macOS 15 (MBP) with version 2.2.21
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
EnConvo Settings Crash Report - macOS Ventura
|
|
||||||
==============================================
|
|
||||||
|
|
||||||
Environment:
|
|
||||||
-----------
|
|
||||||
- Device: MacBook Air (M1)
|
|
||||||
- macOS Version: Ventura 13.6.4 (22G513)
|
|
||||||
- App Version: 2.2.22 (Build 252)
|
|
||||||
- Bundle ID: com.frostyeve.enconvo
|
|
||||||
- Issue: App crashes when clicking Settings sidebar button
|
|
||||||
|
|
||||||
Note: Works fine on macOS 15 (MBP) with version 2.2.21
|
|
||||||
|
|
||||||
Crash Details:
|
|
||||||
--------------
|
|
||||||
Exception Type: EXC_BREAKPOINT
|
|
||||||
Signal: SIGTRAP
|
|
||||||
Termination Reason: Trace/BPT trap: 5
|
|
||||||
Faulting Thread: 0 (Main Thread)
|
|
||||||
|
|
||||||
Crash Location:
|
|
||||||
---------------
|
|
||||||
The crash occurs in AttributeGraph framework during SwiftUI layout operations:
|
|
||||||
|
|
||||||
Stack Trace (Key Frames):
|
|
||||||
- AG::Graph::UpdateStack::update() [AttributeGraph]
|
|
||||||
- AG::Graph::update_attribute() [AttributeGraph]
|
|
||||||
- AG::Graph::input_value_ref_slow() [AttributeGraph]
|
|
||||||
- AGGraphGetValue [AttributeGraph]
|
|
||||||
- NSView layout operations [AppKit]
|
|
||||||
- NSWindow layoutIfNeeded [AppKit]
|
|
||||||
- CATransaction commit [QuartzCore]
|
|
||||||
- CFRunLoopRun [CoreFoundation]
|
|
||||||
- NSApplicationMain [AppKit]
|
|
||||||
|
|
||||||
The crash happens during the layout phase when opening Settings, specifically in:
|
|
||||||
- NSView _layoutSubtreeWithOldSize
|
|
||||||
- NSWindow _layoutViewTree
|
|
||||||
- AttributeGraph update cycle
|
|
||||||
|
|
||||||
Error Description:
|
|
||||||
-----------------
|
|
||||||
The app triggers a breakpoint (EXC_BREAKPOINT) during SwiftUI/AttributeGraph layout
|
|
||||||
operations when the Settings view is being rendered. This suggests a compatibility
|
|
||||||
issue between the SwiftUI/AttributeGraph version in macOS Ventura (13.6.4) and
|
|
||||||
the app's layout code.
|
|
||||||
|
|
||||||
Possible Causes:
|
|
||||||
---------------
|
|
||||||
1. SwiftUI/AttributeGraph API incompatibility between macOS 13 and 15
|
|
||||||
2. Layout constraint or view hierarchy issue specific to macOS 13
|
|
||||||
3. Memory access issue during layout pass on Ventura
|
|
||||||
|
|
||||||
Reproduction Steps:
|
|
||||||
------------------
|
|
||||||
1. Launch EnConvo on macOS Ventura 13.6.4
|
|
||||||
2. Click Settings button in sidebar
|
|
||||||
3. App immediately crashes
|
|
||||||
|
|
||||||
Additional Info:
|
|
||||||
---------------
|
|
||||||
- App runs fine until Settings is clicked
|
|
||||||
- No error dialog shown to user (silent crash)
|
|
||||||
- Crash report generated: EnConvo-2025-11-28-002456.ips
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
EnConvo Pricing & Feature Clarification
|
|
||||||
========================================
|
|
||||||
|
|
||||||
I'm trying to understand the differences between the free and paid versions of EnConvo, particularly regarding API usage and feature limitations.
|
|
||||||
|
|
||||||
Current Understanding:
|
|
||||||
----------------------
|
|
||||||
1. The paid version appears to cover:
|
|
||||||
- API usage fees (for EnConvo's cloud plan)
|
|
||||||
- App updates/maintenance
|
|
||||||
|
|
||||||
2. Free version limitations:
|
|
||||||
- 10 uses/day limit (presumably for EnConvo's cloud plan API)
|
|
||||||
|
|
||||||
Questions:
|
|
||||||
----------
|
|
||||||
|
|
||||||
1. **Using Own API Keys in Free Version:**
|
|
||||||
If I use my own API keys (e.g., OpenAI, Anthropic, etc.) in the free version:
|
|
||||||
- Are there any feature limitations or restrictions?
|
|
||||||
- Does the 10 uses/day limit apply to my own API keys, or only to EnConvo's cloud plan?
|
|
||||||
- Can I use unlimited requests with my own API keys on the free version?
|
|
||||||
|
|
||||||
2. **10 Uses/Day Limit Clarification:**
|
|
||||||
My understanding is that the 10 uses/day limit applies only to EnConvo's cloud plan API usage, not to requests made with my own API keys. Is this correct?
|
|
||||||
|
|
||||||
3. **Cloud Plan vs Own API Keys:**
|
|
||||||
- What are the advantages of using EnConvo's cloud plan (points system) versus using my own API keys?
|
|
||||||
- Does the cloud plan provide access to multiple models that might not be available through direct API access?
|
|
||||||
- Are there any models or features exclusive to the cloud plan?
|
|
||||||
|
|
||||||
4. **Paid Version Benefits:**
|
|
||||||
Beyond covering API costs and updates, are there any additional features, capabilities, or benefits exclusive to the paid version when using your own API keys?
|
|
||||||
|
|
||||||
Summary:
|
|
||||||
--------
|
|
||||||
I want to clarify whether the free version with my own API keys provides full functionality (unlimited usage), or if there are still limitations/restrictions that would require upgrading to the paid version.
|
|
||||||
|
|
||||||
Thank you for your clarification!
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
EnConvo Pricing Question - Free vs Paid
|
|
||||||
========================================
|
|
||||||
|
|
||||||
I'm trying to clarify the differences between free and paid versions, especially regarding API usage.
|
|
||||||
|
|
||||||
My Understanding:
|
|
||||||
-----------------
|
|
||||||
- Paid version covers: API usage fees (EnConvo cloud plan) + app updates
|
|
||||||
- Free version: 10 uses/day limit (for EnConvo's cloud plan API)
|
|
||||||
|
|
||||||
Questions:
|
|
||||||
----------
|
|
||||||
|
|
||||||
1. **Using My Own API Keys:**
|
|
||||||
If I use my own API keys (OpenAI, Anthropic, etc.) in the free version:
|
|
||||||
- Is the 10 uses/day limit still applied, or does it only apply to EnConvo's cloud plan?
|
|
||||||
- Are there any feature limitations when using my own keys?
|
|
||||||
- Can I use unlimited requests with my own API keys on the free version?
|
|
||||||
|
|
||||||
2. **Cloud Plan Benefits:**
|
|
||||||
What advantages does EnConvo's cloud plan offer over using my own API keys directly? (e.g., access to multiple models, better pricing, exclusive features?)
|
|
||||||
|
|
||||||
3. **Paid Version Benefits:**
|
|
||||||
Beyond API costs and updates, are there additional features exclusive to the paid version when using my own API keys?
|
|
||||||
|
|
||||||
In summary: Does the free version with my own API keys provide full, unlimited functionality, or are there still restrictions that require upgrading?
|
|
||||||
|
|
||||||
Thanks!
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Explain Why Moving Files Doesn't Free Space
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Why Moving Files Doesn't Free Space ==="
|
|
||||||
echo ""
|
|
||||||
echo "⚠️ THE PROBLEM:"
|
|
||||||
echo ""
|
|
||||||
echo "When you move/delete files, the OS update snapshot preserves them."
|
|
||||||
echo "This means:"
|
|
||||||
echo " - Files are moved to NAS ✅"
|
|
||||||
echo " - But space isn't freed on Mac ❌"
|
|
||||||
echo " - System Data grows instead 📈"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
FREE_SPACE=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB=$(echo "scale=2; $FREE_SPACE / 1024 / 1024" | bc)
|
|
||||||
echo "Current free space: ${FREE_SPACE_GB}GB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "📸 The OS Update Snapshot:"
|
|
||||||
SNAPSHOT=$(diskutil apfs listSnapshots / 2>/dev/null | grep "Name:" | head -1)
|
|
||||||
if [ -n "$SNAPSHOT" ]; then
|
|
||||||
echo "$SNAPSHOT" | sed 's/^/ /'
|
|
||||||
echo ""
|
|
||||||
echo " This snapshot:"
|
|
||||||
echo " - Is NOT purgeable"
|
|
||||||
echo " - Preserves all deleted/moved files"
|
|
||||||
echo " - Can't be deleted manually"
|
|
||||||
echo " - Will only clear when you update macOS"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🔍 What's Happening:"
|
|
||||||
echo ""
|
|
||||||
echo "1. You move files → Files go to NAS ✅"
|
|
||||||
echo "2. macOS snapshot preserves them → System Data grows 📈"
|
|
||||||
echo "3. Space isn't freed → Still full ❌"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "=== THE ONLY SOLUTION ==="
|
|
||||||
echo ""
|
|
||||||
echo "You MUST install the macOS update to clear the snapshot."
|
|
||||||
echo ""
|
|
||||||
echo "But you need space to install the update (17.64GB needed)."
|
|
||||||
echo ""
|
|
||||||
echo "This is a catch-22 situation:"
|
|
||||||
echo " - Need space to update"
|
|
||||||
echo " - Can't get space because snapshot preserves deleted files"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "=== WORKAROUND ==="
|
|
||||||
echo ""
|
|
||||||
echo "Option 1: Free space from sources that DON'T trigger snapshots:"
|
|
||||||
echo " - Clean caches: rm -rf ~/Library/Caches/* (~6GB)"
|
|
||||||
echo " - Clean user cache: rm -rf ~/.cache/* (~3GB)"
|
|
||||||
echo " - Clean npm: npm cache clean --force (~1GB)"
|
|
||||||
echo " Total: ~10GB (still not enough for 17.64GB update)"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "Option 2: Try downloading update with less space:"
|
|
||||||
echo " sudo softwareupdate --download --all"
|
|
||||||
echo " (Sometimes works with less than required space)"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "Option 3: Use external drive temporarily:"
|
|
||||||
echo " - Move files to external drive (not NAS)"
|
|
||||||
echo " - Install update"
|
|
||||||
echo " - Move files back after snapshot clears"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "Option 4: Contact Apple Support:"
|
|
||||||
echo " They may have tools to force-clear the snapshot"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "=== Current Status ==="
|
|
||||||
echo ""
|
|
||||||
echo "Files moved to NAS: ✅ (they're safe)"
|
|
||||||
echo "Space freed on Mac: ❌ (snapshot preserving them)"
|
|
||||||
echo "System Data: 📈 (growing because of snapshot)"
|
|
||||||
echo ""
|
|
||||||
echo "The files ARE moved, but the space won't be freed"
|
|
||||||
echo "until the snapshot is cleared by updating macOS."
|
|
||||||
echo ""
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Final Explanation - Why Nothing Works
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== FINAL EXPLANATION ==="
|
|
||||||
echo ""
|
|
||||||
echo "You've tried everything:"
|
|
||||||
echo " ✅ Moved files to NAS"
|
|
||||||
echo " ✅ Moved files to external drive"
|
|
||||||
echo " ✅ Cleaned caches"
|
|
||||||
echo " ❌ Still no space freed"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
FREE_SPACE=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB=$(echo "scale=2; $FREE_SPACE / 1024 / 1024" | bc)
|
|
||||||
echo "Current free space: ${FREE_SPACE_GB}GB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "❌ WHY NOTHING WORKS:"
|
|
||||||
echo ""
|
|
||||||
echo "The OS update snapshot preserves EVERYTHING:"
|
|
||||||
echo " - Deleted files → Preserved in snapshot"
|
|
||||||
echo " - Moved files → Preserved in snapshot"
|
|
||||||
echo " - Files on NAS → Still preserved in snapshot"
|
|
||||||
echo " - Files on external drive → Still preserved in snapshot"
|
|
||||||
echo ""
|
|
||||||
echo "The snapshot doesn't care WHERE files went."
|
|
||||||
echo "It preserves them regardless of destination."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "📸 The Snapshot:"
|
|
||||||
SNAPSHOT=$(diskutil apfs listSnapshots / 2>/dev/null | grep "Name:" | head -1)
|
|
||||||
if [ -n "$SNAPSHOT" ]; then
|
|
||||||
echo "$SNAPSHOT" | sed 's/^/ /'
|
|
||||||
echo ""
|
|
||||||
echo " - NOT purgeable"
|
|
||||||
echo " - Preserves ALL file operations"
|
|
||||||
echo " - Can't be deleted"
|
|
||||||
echo " - Only clears when macOS updates"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🔒 THE CATCH-22:"
|
|
||||||
echo ""
|
|
||||||
echo " Need: 17.64GB to install macOS update"
|
|
||||||
echo " Problem: Can't free space (snapshot preserves everything)"
|
|
||||||
echo " Result: Stuck"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "✅ YOUR ONLY OPTIONS:"
|
|
||||||
echo ""
|
|
||||||
echo "1. **Contact Apple Support** (RECOMMENDED)"
|
|
||||||
echo " Phone: 1-800-275-2273"
|
|
||||||
echo " Explain: 'OS update snapshot preventing space recovery'"
|
|
||||||
echo " They have system-level tools we don't have access to"
|
|
||||||
echo ""
|
|
||||||
echo "2. **Try GUI Update** (Sometimes works differently)"
|
|
||||||
echo " System Settings → General → Software Update"
|
|
||||||
echo " Click 'Update Now'"
|
|
||||||
echo " GUI sometimes bypasses space checks"
|
|
||||||
echo ""
|
|
||||||
echo "3. **Boot from Recovery** (Advanced)"
|
|
||||||
echo " - Restart holding Command+R"
|
|
||||||
echo " - Try updating from Recovery Mode"
|
|
||||||
echo " - May have different space requirements"
|
|
||||||
echo ""
|
|
||||||
echo "4. **Wait for Automatic Cleanup** (Unreliable)"
|
|
||||||
echo " macOS may eventually clear old snapshots"
|
|
||||||
echo " But this can take weeks/months"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "📊 Current Situation:"
|
|
||||||
echo ""
|
|
||||||
echo " Files moved: ✅ (Safe on NAS/external drive)"
|
|
||||||
echo " Space freed: ❌ (Snapshot preserving them)"
|
|
||||||
echo " System Data: 📈 (351GB+ and growing)"
|
|
||||||
echo " Free space: ${FREE_SPACE_GB}GB (not enough)"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "⚠️ IMPORTANT:"
|
|
||||||
echo ""
|
|
||||||
echo "Your files ARE safe. The space WILL be freed after updating."
|
|
||||||
echo "But you're in a system-level catch-22 that requires"
|
|
||||||
echo "Apple Support intervention or advanced recovery methods."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🎯 NEXT STEP:"
|
|
||||||
echo ""
|
|
||||||
echo "Call Apple Support: 1-800-275-2273"
|
|
||||||
echo "They can help with this specific issue."
|
|
||||||
echo ""
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Final Solution Summary - Why Moving Files Doesn't Free Space
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== FINAL SOLUTION SUMMARY ==="
|
|
||||||
echo ""
|
|
||||||
echo "You've moved files (Music, Documents, etc.) to NAS,"
|
|
||||||
echo "but space isn't being freed. Here's why and what to do:"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
FREE_SPACE=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB=$(echo "scale=2; $FREE_SPACE / 1024 / 1024" | bc)
|
|
||||||
echo "Current free space: ${FREE_SPACE_GB}GB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "❌ THE PROBLEM:"
|
|
||||||
echo ""
|
|
||||||
echo "The OS update snapshot is preserving ALL moved/deleted files."
|
|
||||||
echo ""
|
|
||||||
echo "What happens:"
|
|
||||||
echo " 1. You move Music folder → Files go to NAS ✅"
|
|
||||||
echo " 2. Snapshot preserves them → System Data grows 📈"
|
|
||||||
echo " 3. Space NOT freed → Still full ❌"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "📸 The Snapshot:"
|
|
||||||
SNAPSHOT=$(diskutil apfs listSnapshots / 2>/dev/null | grep "Name:" | head -1)
|
|
||||||
if [ -n "$SNAPSHOT" ]; then
|
|
||||||
echo "$SNAPSHOT" | sed 's/^/ /'
|
|
||||||
echo ""
|
|
||||||
echo " - NOT purgeable"
|
|
||||||
echo " - Preserves all deleted/moved files"
|
|
||||||
echo " - Can't be deleted manually"
|
|
||||||
echo " - Only clears when you update macOS"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "✅ THE ONLY SOLUTION:"
|
|
||||||
echo ""
|
|
||||||
echo "You MUST install the macOS update to clear the snapshot."
|
|
||||||
echo ""
|
|
||||||
echo "But you need 17.64GB to install, and you can't free space"
|
|
||||||
echo "because the snapshot preserves everything you delete/move."
|
|
||||||
echo ""
|
|
||||||
echo "This is a SYSTEM-LEVEL CATCH-22."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🔧 WORKAROUNDS:"
|
|
||||||
echo ""
|
|
||||||
echo "1. **Try downloading update anyway** (may work with less space):"
|
|
||||||
echo " sudo softwareupdate --download --all"
|
|
||||||
echo ""
|
|
||||||
echo "2. **Use external drive** (if available):"
|
|
||||||
echo " - Connect external drive"
|
|
||||||
echo " - Move large files there (not NAS)"
|
|
||||||
echo " - Install update"
|
|
||||||
echo " - Move files back after snapshot clears"
|
|
||||||
echo ""
|
|
||||||
echo "3. **Contact Apple Support**:"
|
|
||||||
echo " - They may have tools to force-clear snapshot"
|
|
||||||
echo " - Or can help with update process"
|
|
||||||
echo " - Phone: 1-800-275-2273"
|
|
||||||
echo ""
|
|
||||||
echo "4. **Try restarting, then immediately download update**:"
|
|
||||||
echo " - Restart Mac"
|
|
||||||
echo " - Immediately run: sudo softwareupdate --download --all"
|
|
||||||
echo " - Sometimes releases temporary space"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "📊 Current Status:"
|
|
||||||
echo ""
|
|
||||||
echo " Files moved to NAS: ✅ (they're safe)"
|
|
||||||
echo " Space freed on Mac: ❌ (snapshot preserving them)"
|
|
||||||
echo " System Data: 📈 (351GB+ and growing)"
|
|
||||||
echo " Free space: ${FREE_SPACE_GB}GB (not enough for update)"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "⚠️ IMPORTANT:"
|
|
||||||
echo ""
|
|
||||||
echo " - Your files ARE safely on NAS"
|
|
||||||
echo " - The space WILL be freed after updating macOS"
|
|
||||||
echo " - But you need space to update (catch-22)"
|
|
||||||
echo " - This requires external storage or Apple Support"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🎯 RECOMMENDED ACTION:"
|
|
||||||
echo ""
|
|
||||||
echo " 1. Try: sudo softwareupdate --download --all"
|
|
||||||
echo " (May work even with current space)"
|
|
||||||
echo ""
|
|
||||||
echo " 2. If that fails, use external drive or contact Apple Support"
|
|
||||||
echo ""
|
|
||||||
@@ -1,108 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Find ANY Freeable Space - Check everything
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Find Any Freeable Space ==="
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
FREE_SPACE=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB=$(echo "scale=2; $FREE_SPACE / 1024 / 1024" | bc)
|
|
||||||
echo "Current free space: ${FREE_SPACE_GB}GB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🔍 Checking all possible sources of space:"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
TOTAL_POTENTIAL=0
|
|
||||||
|
|
||||||
# 1. Caches
|
|
||||||
echo "1. Caches:"
|
|
||||||
CACHE_SIZE=$(du -sh ~/Library/Caches 2>/dev/null | awk '{print $1}' || echo "0")
|
|
||||||
echo " Library/Caches: $CACHE_SIZE"
|
|
||||||
if [ "$CACHE_SIZE" != "0" ] && [ -n "$CACHE_SIZE" ]; then
|
|
||||||
CACHE_GB=$(echo "$CACHE_SIZE" | sed 's/G//' | awk '{if ($1 ~ /[0-9]/) print $1; else print "0"}')
|
|
||||||
TOTAL_POTENTIAL=$(echo "$TOTAL_POTENTIAL + $CACHE_GB" | bc 2>/dev/null || echo "$TOTAL_POTENTIAL")
|
|
||||||
fi
|
|
||||||
|
|
||||||
USER_CACHE=$(du -sh ~/.cache 2>/dev/null | awk '{print $1}' || echo "0")
|
|
||||||
echo " .cache: $USER_CACHE"
|
|
||||||
|
|
||||||
NPM_CACHE=$(du -sh ~/.npm 2>/dev/null | awk '{print $1}' || echo "0")
|
|
||||||
echo " .npm: $NPM_CACHE"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 2. Downloads
|
|
||||||
DOWNLOADS=$(du -sh ~/Downloads 2>/dev/null | awk '{print $1}' || echo "0")
|
|
||||||
echo "2. Downloads: $DOWNLOADS"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 3. Trash
|
|
||||||
TRASH=$(du -sh ~/.Trash 2>/dev/null | awk '{print $1}' || echo "0")
|
|
||||||
echo "3. Trash: $TRASH"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 4. Virtual memory
|
|
||||||
VM_SIZE=$(sudo du -sh /private/var/vm 2>/dev/null | awk '{print $1}' || echo "0")
|
|
||||||
echo "4. Virtual Memory (swap): $VM_SIZE"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 5. System temp
|
|
||||||
TEMP_SIZE=$(sudo du -sh /private/var/folders 2>/dev/null | awk '{print $1}' || echo "0")
|
|
||||||
echo "5. System Temp: $TEMP_SIZE"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 6. Large directories
|
|
||||||
echo "6. Large Directories:"
|
|
||||||
OLLAMA=$(du -sh ~/.ollama 2>/dev/null | awk '{print $1}' || echo "0")
|
|
||||||
echo " .ollama: $OLLAMA"
|
|
||||||
|
|
||||||
LOCAL=$(du -sh ~/.local 2>/dev/null | awk '{print $1}' || echo "0")
|
|
||||||
echo " .local: $LOCAL"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 7. Documents remaining
|
|
||||||
DOCS=$(du -sh ~/Documents 2>/dev/null | awk '{print $1}' || echo "0")
|
|
||||||
echo "7. Documents remaining: $DOCS"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "=== Analysis ==="
|
|
||||||
echo ""
|
|
||||||
echo "The problem: Even if we free space, the OS snapshot will preserve"
|
|
||||||
echo "deleted files, making System Data grow instead."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "=== Desperate Measures ==="
|
|
||||||
echo ""
|
|
||||||
echo "Since normal methods don't work, try:"
|
|
||||||
echo ""
|
|
||||||
echo "1. **Restart your Mac**"
|
|
||||||
echo " Sometimes releases some purgeable space temporarily"
|
|
||||||
echo ""
|
|
||||||
echo "2. **Try downloading update with current space**"
|
|
||||||
echo " sudo softwareupdate --download --all"
|
|
||||||
echo " (May work even with less than 17.64GB)"
|
|
||||||
echo ""
|
|
||||||
echo "3. **Check if update can install incrementally**"
|
|
||||||
echo " System Settings → General → Software Update"
|
|
||||||
echo " Click 'More Info' to see if it can download in parts"
|
|
||||||
echo ""
|
|
||||||
echo "4. **Use external drive** (if available)"
|
|
||||||
echo " - Connect external drive"
|
|
||||||
echo " - Move large files there (not NAS)"
|
|
||||||
echo " - Install update"
|
|
||||||
echo " - Move files back"
|
|
||||||
echo ""
|
|
||||||
echo "5. **Contact Apple Support**"
|
|
||||||
echo " They may have tools to force-clear the snapshot"
|
|
||||||
echo " Or can help with the update process"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "=== The Real Issue ==="
|
|
||||||
echo ""
|
|
||||||
echo "The OS update snapshot is blocking everything."
|
|
||||||
echo "You need to update macOS, but need space to update."
|
|
||||||
echo "This is a system-level catch-22 that may require"
|
|
||||||
echo "Apple Support intervention or external storage."
|
|
||||||
echo ""
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Find Large Files - Help locate where space is actually being used
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Find Large Files ==="
|
|
||||||
echo ""
|
|
||||||
echo "Your container is 99.8% full (493.5GB used, 847MB free)"
|
|
||||||
echo "Let's find where the space is actually being used..."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "📊 Top Space Users:"
|
|
||||||
echo ""
|
|
||||||
echo "Home directory breakdown:"
|
|
||||||
du -h -d 1 ~ 2>/dev/null | sort -hr | head -10 | awk '{printf " %8s %s\n", $1, $2}'
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🔍 Large Files (>1GB) in Home:"
|
|
||||||
echo " Searching... (this may take a moment)"
|
|
||||||
find ~ -size +1G -type f 2>/dev/null | head -10 | while read file; do
|
|
||||||
SIZE=$(du -h "$file" 2>/dev/null | awk '{print $1}')
|
|
||||||
echo " $SIZE $file"
|
|
||||||
done
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "📁 Large Directories in Documents (40GB):"
|
|
||||||
du -h -d 1 ~/Documents 2>/dev/null | sort -hr | head -10 | awk '{printf " %8s %s\n", $1, $2}'
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "📚 Large Directories in Library (33GB):"
|
|
||||||
du -h -d 1 ~/Library 2>/dev/null | sort -hr | head -10 | awk '{printf " %8s %s\n", $1, $2}'
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "💾 Other Large Locations:"
|
|
||||||
echo " .local: $(du -sh ~/.local 2>/dev/null | awk '{print $1}')"
|
|
||||||
echo " .ollama: $(du -sh ~/.ollama 2>/dev/null | awk '{print $1}')"
|
|
||||||
echo " Downloads: $(du -sh ~/Downloads 2>/dev/null | awk '{print $1}')"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "=== Questions ==="
|
|
||||||
echo ""
|
|
||||||
echo "1. Where exactly did you delete the 20GB from?"
|
|
||||||
echo " - Was it from ~/Movies? (currently 6.7GB)"
|
|
||||||
echo " - Or another location?"
|
|
||||||
echo ""
|
|
||||||
echo "2. Did you verify the files were actually deleted?"
|
|
||||||
echo " - Check the original location"
|
|
||||||
echo " - Check Trash (currently empty)"
|
|
||||||
echo ""
|
|
||||||
echo "3. The container shows 493.5GB used:"
|
|
||||||
echo " - Data volume: 471.8GB"
|
|
||||||
echo " - System volume: 12.2GB"
|
|
||||||
echo " - Preboot: 8.1GB"
|
|
||||||
echo " - Recovery: 1.2GB"
|
|
||||||
echo ""
|
|
||||||
echo " Your home directory is 130GB, but the Data volume is 471.8GB"
|
|
||||||
echo " This means there are other users or system files using space."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "=== Recommendations ==="
|
|
||||||
echo ""
|
|
||||||
echo "To free space immediately:"
|
|
||||||
echo ""
|
|
||||||
echo "1. Clean Downloads: $(du -sh ~/Downloads 2>/dev/null | awk '{print $1}')"
|
|
||||||
echo " rm -rf ~/Downloads/*"
|
|
||||||
echo ""
|
|
||||||
echo "2. Clean Library Caches:"
|
|
||||||
echo " rm -rf ~/Library/Caches/*"
|
|
||||||
echo ""
|
|
||||||
echo "3. Review Documents folder (40GB):"
|
|
||||||
echo " Move large files to NAS"
|
|
||||||
echo ""
|
|
||||||
echo "4. Review .ollama folder (17GB):"
|
|
||||||
echo " Remove unused AI models"
|
|
||||||
echo ""
|
|
||||||
echo "5. Use macOS Storage Management:"
|
|
||||||
echo " Apple Menu → About This Mac → Storage → Manage"
|
|
||||||
echo ""
|
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Find Real 351GB Usage in System Data
|
|
||||||
# Since purgeable space test failed, the space is actually being used
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Find Real 351GB Usage in System Data ==="
|
|
||||||
echo ""
|
|
||||||
echo "The 50GB file creation FAILED, which means:"
|
|
||||||
echo " - The 351GB is NOT purgeable"
|
|
||||||
echo " - It's actually being used"
|
|
||||||
echo " - We need to find what's using it"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "📊 Container Analysis:"
|
|
||||||
CONTAINER_TOTAL=$(diskutil info / | grep 'Container Total' | awk '{print $4, $5}')
|
|
||||||
CONTAINER_FREE=$(diskutil info / | grep 'Container Free' | awk '{print $4, $5}')
|
|
||||||
CONTAINER_USED=$(diskutil apfs list 2>/dev/null | grep "Capacity In Use" | awk '{print $6, $7}')
|
|
||||||
|
|
||||||
echo " Container Total: $CONTAINER_TOTAL"
|
|
||||||
echo " Container Free: $CONTAINER_FREE"
|
|
||||||
echo " Container Used: $CONTAINER_USED"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "📦 APFS Volume Breakdown:"
|
|
||||||
diskutil apfs list 2>/dev/null | grep -E "Volume|Capacity Consumed" | while read line; do
|
|
||||||
if echo "$line" | grep -q "Volume"; then
|
|
||||||
VOL_NAME=$(echo "$line" | sed 's/.*Name: *\([^(]*\).*/\1/')
|
|
||||||
echo " Volume: $VOL_NAME"
|
|
||||||
elif echo "$line" | grep -q "Capacity Consumed"; then
|
|
||||||
SIZE=$(echo "$line" | awk '{print $3, $4}')
|
|
||||||
echo " Size: $SIZE"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "📸 APFS Snapshots:"
|
|
||||||
APFS_SNAPS=$(diskutil apfs listSnapshots / 2>/dev/null)
|
|
||||||
if [ -n "$APFS_SNAPS" ]; then
|
|
||||||
echo "$APFS_SNAPS" | head -20 | sed 's/^/ /'
|
|
||||||
echo ""
|
|
||||||
echo " ⚠️ The OS update snapshot may be holding space"
|
|
||||||
echo " This snapshot is NOT purgeable and can't be deleted"
|
|
||||||
else
|
|
||||||
echo " No snapshots found"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🔍 Large System Directories:"
|
|
||||||
echo " /System:"
|
|
||||||
sudo du -h -d 2 /System/Volumes/Data/System 2>/dev/null | sort -hr | head -5 | awk '{printf " %8s %s\n", $1, $2}'
|
|
||||||
echo ""
|
|
||||||
echo " /Library:"
|
|
||||||
sudo du -h -d 2 /System/Volumes/Data/Library 2>/dev/null | sort -hr | head -5 | awk '{printf " %8s %s\n", $1, $2}'
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🔍 Searching for large files (>10GB)..."
|
|
||||||
echo " (This may take a moment)"
|
|
||||||
LARGE_FILES=$(sudo find /System/Volumes/Data -type f -size +10G 2>/dev/null | head -5)
|
|
||||||
if [ -n "$LARGE_FILES" ]; then
|
|
||||||
echo "$LARGE_FILES" | while read file; do
|
|
||||||
SIZE=$(sudo du -h "$file" 2>/dev/null | awk '{print $1}')
|
|
||||||
echo " $SIZE $file"
|
|
||||||
done
|
|
||||||
else
|
|
||||||
echo " No files >10GB found"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "=== Analysis ==="
|
|
||||||
echo ""
|
|
||||||
echo "The 351GB in System Data is likely:"
|
|
||||||
echo ""
|
|
||||||
echo "1. **APFS Snapshot Overhead** (Most Likely)"
|
|
||||||
echo " - The OS update snapshot (12.2GB visible)"
|
|
||||||
echo " - May be holding 300+ GB of deleted file space"
|
|
||||||
echo " - APFS snapshots preserve deleted files"
|
|
||||||
echo " - This space is NOT purgeable until snapshot is deleted"
|
|
||||||
echo ""
|
|
||||||
echo "2. **Time Machine Local Snapshots**"
|
|
||||||
echo " - The stuck snapshot entry"
|
|
||||||
echo " - May be holding space even though it's a 'ghost'"
|
|
||||||
echo ""
|
|
||||||
echo "3. **System Reserved Space**"
|
|
||||||
echo " - macOS reserves space for operations"
|
|
||||||
echo " - Shown in System Data but not easily identifiable"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "=== Solution ==="
|
|
||||||
echo ""
|
|
||||||
echo "The OS update snapshot CANNOT be deleted (it's required)."
|
|
||||||
echo "However, you can try:"
|
|
||||||
echo ""
|
|
||||||
echo "1. **Update macOS** (if available):"
|
|
||||||
echo " System Settings → General → Software Update"
|
|
||||||
echo " Installing updates may clear old snapshots"
|
|
||||||
echo ""
|
|
||||||
echo "2. **Check for macOS Install Data** (11GB found):"
|
|
||||||
echo " sudo rm -rf /System/Volumes/Data/macOS\ Install\ Data"
|
|
||||||
echo " (Safe to delete after installation completes)"
|
|
||||||
echo ""
|
|
||||||
echo "3. **The space may be in APFS snapshot overhead**:"
|
|
||||||
echo " This is space held by the OS update snapshot"
|
|
||||||
echo " It will be released when you update macOS"
|
|
||||||
echo ""
|
|
||||||
echo "4. **Check Storage Management for details**:"
|
|
||||||
echo " Apple Menu → About This Mac → Storage"
|
|
||||||
echo " Hover over 'System Data' for more details"
|
|
||||||
echo ""
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Find Real Space Usage
|
|
||||||
# The snapshot is a ghost - find what's actually using space
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Find Real Space Usage ==="
|
|
||||||
echo ""
|
|
||||||
echo "Your container is 99.8% full (493.4GB used, 995MB free)"
|
|
||||||
echo "The snapshot is a ghost entry (0GB)."
|
|
||||||
echo "Let's find what's ACTUALLY using the space..."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "📊 Container Breakdown:"
|
|
||||||
echo " Container Total: 494.4GB"
|
|
||||||
echo " Container Used: 493.4GB (99.8%)"
|
|
||||||
echo " Container Free: 995MB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🔍 Large Directories in /System/Volumes/Data:"
|
|
||||||
sudo du -h -d 1 /System/Volumes/Data 2>/dev/null | sort -hr | head -10 | awk '{printf " %8s %s\n", $1, $2}'
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check the suspicious Volumes directory
|
|
||||||
VOLUMES_SIZE=$(sudo du -sh /System/Volumes/Data/Volumes 2>/dev/null | awk '{print $1}')
|
|
||||||
echo "⚠️ CRITICAL FINDING:"
|
|
||||||
echo " /System/Volumes/Data/Volumes: $VOLUMES_SIZE"
|
|
||||||
echo ""
|
|
||||||
echo " This directory is HUGE and likely contains:"
|
|
||||||
echo " - Old Time Machine backup volumes"
|
|
||||||
echo " - Mounted disk images"
|
|
||||||
echo " - Stale mount points"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🔍 Checking what's in /System/Volumes/Data/Volumes:"
|
|
||||||
ls -la /System/Volumes/Data/Volumes/ 2>/dev/null | head -20 | sed 's/^/ /'
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check for old backup volumes
|
|
||||||
echo "📦 Checking for old Time Machine backup volumes:"
|
|
||||||
BACKUP_VOLS=$(ls -d "/System/Volumes/Data/Volumes/Backups of"* 2>/dev/null || echo "")
|
|
||||||
if [ -n "$BACKUP_VOLS" ]; then
|
|
||||||
echo " Found old backup volumes:"
|
|
||||||
echo "$BACKUP_VOLS" | while read vol; do
|
|
||||||
SIZE=$(sudo du -sh "$vol" 2>/dev/null | awk '{print $1}')
|
|
||||||
echo " - $vol ($SIZE)"
|
|
||||||
done
|
|
||||||
echo ""
|
|
||||||
echo " ⚠️ These are likely old Time Machine backups taking up space!"
|
|
||||||
else
|
|
||||||
echo " No obvious backup volumes found"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check home directory
|
|
||||||
echo "📁 Your Home Directory:"
|
|
||||||
du -h -d 1 ~ 2>/dev/null | sort -hr | head -10 | awk '{printf " %8s %s\n", $1, $2}'
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Summary
|
|
||||||
echo "=== Summary ==="
|
|
||||||
echo ""
|
|
||||||
echo "The snapshot is NOT the problem (it's a ghost, 0GB)."
|
|
||||||
echo ""
|
|
||||||
echo "The REAL problem:"
|
|
||||||
echo " - Container is 99.8% full"
|
|
||||||
echo " - /System/Volumes/Data/Volumes is $VOLUMES_SIZE (likely old backups)"
|
|
||||||
echo " - Your home: 130GB"
|
|
||||||
echo ""
|
|
||||||
echo "To free space, you need to:"
|
|
||||||
echo " 1. Check what's in /System/Volumes/Data/Volumes"
|
|
||||||
echo " 2. Remove old backup volumes if found"
|
|
||||||
echo " 3. Clean up your home directory:"
|
|
||||||
echo " - Downloads: 8.7GB"
|
|
||||||
echo " - Documents: 40GB"
|
|
||||||
echo " - Library: 33GB"
|
|
||||||
echo ""
|
|
||||||
@@ -1,129 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Find What's in System Data (351GB)
|
|
||||||
# System Data includes snapshots, caches, logs, VM files, etc.
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Find System Data Usage (351GB) ==="
|
|
||||||
echo ""
|
|
||||||
echo "System Data on macOS includes:"
|
|
||||||
echo " - APFS snapshots"
|
|
||||||
echo " - Time Machine local snapshots"
|
|
||||||
echo " - Virtual memory swap files"
|
|
||||||
echo " - System caches"
|
|
||||||
echo " - Log files"
|
|
||||||
echo " - Purgeable space"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
TOTAL_FOUND=0
|
|
||||||
|
|
||||||
echo "🔍 Checking System Data Components:"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 1. Check APFS snapshots
|
|
||||||
echo "1. APFS Snapshots:"
|
|
||||||
APFS_SNAPS=$(diskutil apfs listSnapshots / 2>/dev/null | grep -c "Name:" || echo "0")
|
|
||||||
echo " Found: $APFS_SNAPS snapshot(s)"
|
|
||||||
if [ "$APFS_SNAPS" -gt 0 ]; then
|
|
||||||
diskutil apfs listSnapshots / 2>/dev/null | grep -E "Name|Purgeable" | head -4 | sed 's/^/ /'
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 2. Check Time Machine local snapshots
|
|
||||||
echo "2. Time Machine Local Snapshots:"
|
|
||||||
TM_SNAPS=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$" | wc -l | tr -d ' ')
|
|
||||||
echo " Found: $TM_SNAPS snapshot(s)"
|
|
||||||
if [ "$TM_SNAPS" -gt 0 ]; then
|
|
||||||
tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$" | sed 's/^/ - /'
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 3. Check virtual memory (swap files)
|
|
||||||
echo "3. Virtual Memory (Swap Files):"
|
|
||||||
VM_SIZE=$(sudo du -sh /private/var/vm 2>/dev/null | awk '{print $1}' || echo "0")
|
|
||||||
echo " /private/var/vm: $VM_SIZE"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 4. Check system caches
|
|
||||||
echo "4. System Caches:"
|
|
||||||
CACHE_SIZE=$(sudo du -sh /private/var/folders 2>/dev/null | awk '{print $1}' || echo "0")
|
|
||||||
echo " /private/var/folders: $CACHE_SIZE"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 5. Check logs
|
|
||||||
echo "5. System Logs:"
|
|
||||||
LOG_SIZE=$(sudo du -sh /Library/Logs /private/var/log 2>/dev/null 2>/dev/null | awk '{sum+=$1} END {print sum}' || echo "0")
|
|
||||||
echo " Logs: ~$LOG_SIZE"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 6. Check MobileBackups
|
|
||||||
echo "6. MobileBackups (APFS Local Snapshots):"
|
|
||||||
MB_SIZE=$(sudo du -sh /System/Volumes/Data/.MobileBackups /.MobileBackups 2>/dev/null | awk '{sum+=$1} END {print sum}' || echo "0")
|
|
||||||
if [ "$MB_SIZE" != "0" ] && [ -n "$MB_SIZE" ]; then
|
|
||||||
echo " MobileBackups: $MB_SIZE"
|
|
||||||
else
|
|
||||||
echo " MobileBackups: Not found or empty"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 7. Check /private/var
|
|
||||||
echo "7. /private/var (System Data):"
|
|
||||||
PVAR_SIZE=$(sudo du -sh /System/Volumes/Data/private/var 2>/dev/null | awk '{print $1}' || echo "0")
|
|
||||||
echo " /private/var: $PVAR_SIZE"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 8. Check for sparse bundles
|
|
||||||
echo "8. Sparse Bundles (Disk Images):"
|
|
||||||
SPARSE_COUNT=$(sudo find /System/Volumes/Data -maxdepth 3 -name "*.sparsebundle" -o -name "*.sparseimage" 2>/dev/null | wc -l | tr -d ' ')
|
|
||||||
echo " Found: $SPARSE_COUNT sparse bundle(s)"
|
|
||||||
if [ "$SPARSE_COUNT" -gt 0 ]; then
|
|
||||||
sudo find /System/Volumes/Data -maxdepth 3 -name "*.sparsebundle" -o -name "*.sparseimage" 2>/dev/null | head -5 | while read bundle; do
|
|
||||||
SIZE=$(sudo du -sh "$bundle" 2>/dev/null | awk '{print $1}')
|
|
||||||
echo " - $bundle ($SIZE)"
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 9. Check Library
|
|
||||||
echo "9. System Library:"
|
|
||||||
LIB_SIZE=$(sudo du -sh /System/Volumes/Data/Library 2>/dev/null | awk '{print $1}' || echo "0")
|
|
||||||
echo " /Library: $LIB_SIZE"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "=== Summary ==="
|
|
||||||
echo ""
|
|
||||||
echo "System Data is 351GB. The components above may not add up to 351GB"
|
|
||||||
echo "because System Data also includes:"
|
|
||||||
echo " - Purgeable space (not shown in du)"
|
|
||||||
echo " - APFS snapshot overhead"
|
|
||||||
echo " - Reserved space"
|
|
||||||
echo " - Other system files"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🔧 To Reduce System Data:"
|
|
||||||
echo ""
|
|
||||||
echo "1. Delete Time Machine local snapshots:"
|
|
||||||
if [ "$TM_SNAPS" -gt 0 ]; then
|
|
||||||
echo " sudo tmutil deletelocalsnapshots <date>"
|
|
||||||
else
|
|
||||||
echo " (No snapshots found)"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "2. Thin local snapshots:"
|
|
||||||
echo " sudo tmutil thinlocalsnapshots / 1000000000 1"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "3. Remove Time Machine destination (prevents new snapshots):"
|
|
||||||
echo " System Settings → Time Machine → Remove backup disk"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "4. Clean system caches:"
|
|
||||||
echo " sudo rm -rf /private/var/folders/*"
|
|
||||||
echo " (⚠️ Be careful - this may affect running apps)"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "5. Restart your Mac:"
|
|
||||||
echo " This often releases purgeable space and snapshots"
|
|
||||||
echo ""
|
|
||||||
@@ -1,146 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Find Time Machine System Files
|
|
||||||
# This script identifies Time Machine files in system locations that may be taking up 100GB+
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Time Machine System Files Finder ==="
|
|
||||||
echo ""
|
|
||||||
echo "Searching for Time Machine files in system locations..."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
TOTAL_SIZE=0
|
|
||||||
|
|
||||||
# Function to check and report size
|
|
||||||
check_location() {
|
|
||||||
local path=$1
|
|
||||||
local description=$2
|
|
||||||
|
|
||||||
if [ -e "$path" ]; then
|
|
||||||
SIZE=$(sudo du -sh "$path" 2>/dev/null | awk '{print $1}')
|
|
||||||
SIZE_BYTES=$(sudo du -sb "$path" 2>/dev/null | awk '{print $1}')
|
|
||||||
if [ -n "$SIZE_BYTES" ] && [ "$SIZE_BYTES" -gt 0 ]; then
|
|
||||||
echo " ✓ $description: $SIZE"
|
|
||||||
echo " Path: $path"
|
|
||||||
TOTAL_SIZE=$((TOTAL_SIZE + SIZE_BYTES))
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
echo "🔍 Checking Time Machine locations:"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 1. Local snapshots
|
|
||||||
echo "1. Local Snapshots:"
|
|
||||||
SNAPSHOTS=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$" | wc -l | tr -d ' ')
|
|
||||||
if [ "$SNAPSHOTS" -gt 0 ]; then
|
|
||||||
echo " Found $SNAPSHOTS snapshot(s):"
|
|
||||||
tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$" | while read snapshot; do
|
|
||||||
echo " - $snapshot"
|
|
||||||
# Get snapshot size (requires root)
|
|
||||||
SNAP_SIZE=$(sudo tmutil calculatedrift "$snapshot" 2>/dev/null | grep -i "size" | tail -1 || echo "")
|
|
||||||
if [ -n "$SNAP_SIZE" ]; then
|
|
||||||
echo " $SNAP_SIZE"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
else
|
|
||||||
echo " No local snapshots found"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 2. MobileBackups (APFS snapshots location)
|
|
||||||
echo "2. MobileBackups (APFS Snapshots):"
|
|
||||||
check_location "/System/Volumes/Data/.MobileBackups" "MobileBackups (newer macOS)"
|
|
||||||
check_location "/.MobileBackups" "MobileBackups (older macOS)"
|
|
||||||
check_location "/private/var/.MobileBackups" "MobileBackups (alternate location)"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 3. Time Machine sparse bundles in system locations
|
|
||||||
echo "3. Time Machine Sparse Bundles:"
|
|
||||||
find /private/var -name "*.sparsebundle" -o -name "*.sparseimage" 2>/dev/null | while read bundle; do
|
|
||||||
if [ -e "$bundle" ]; then
|
|
||||||
SIZE=$(sudo du -sh "$bundle" 2>/dev/null | awk '{print $1}')
|
|
||||||
echo " Found: $bundle ($SIZE)"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
find /System/Volumes/Data -maxdepth 3 -name "*.sparsebundle" -o -name "*.sparseimage" 2>/dev/null | while read bundle; do
|
|
||||||
if [ -e "$bundle" ]; then
|
|
||||||
SIZE=$(sudo du -sh "$bundle" 2>/dev/null | awk '{print $1}')
|
|
||||||
echo " Found: $bundle ($SIZE)"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 4. Time Machine preferences and data
|
|
||||||
echo "4. Time Machine System Data:"
|
|
||||||
check_location "/Library/Preferences/com.apple.TimeMachine.plist" "Time Machine preferences"
|
|
||||||
check_location "/private/var/db/timezone" "Timezone data (may contain backups)"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 5. Check for old backup files in /private/var
|
|
||||||
echo "5. System Backup Directories:"
|
|
||||||
check_location "/private/var/backups" "System backups"
|
|
||||||
check_location "/private/var/db" "Database files (may contain backup data)"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 6. Check for Time Machine logs (usually small but let's check)
|
|
||||||
echo "6. Time Machine Logs:"
|
|
||||||
LOG_SIZE=$(sudo du -sh /private/var/log/com.apple.TimeMachine* 2>/dev/null | awk '{sum+=$1} END {print sum}' || echo "0")
|
|
||||||
if [ "$LOG_SIZE" != "0" ] && [ -n "$LOG_SIZE" ]; then
|
|
||||||
echo " Log files: $LOG_SIZE"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 7. Check System/Volumes/Data for large Time Machine related files
|
|
||||||
echo "7. System Volumes Data:"
|
|
||||||
echo " Checking for large directories in /System/Volumes/Data..."
|
|
||||||
sudo du -h -d 2 /System/Volumes/Data 2>/dev/null | grep -i "timemachine\|backup\|snapshot" | sort -hr | head -10 | while read line; do
|
|
||||||
echo " $line"
|
|
||||||
done
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 8. Check for old Time Machine destinations
|
|
||||||
echo "8. Time Machine Backup Destinations:"
|
|
||||||
tmutil listbackups 2>/dev/null | head -5
|
|
||||||
BACKUP_COUNT=$(tmutil listbackups 2>/dev/null | wc -l | tr -d ' ')
|
|
||||||
if [ "$BACKUP_COUNT" -gt 0 ]; then
|
|
||||||
echo " Total backups listed: $BACKUP_COUNT"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 9. Check disk space breakdown
|
|
||||||
echo "9. Disk Space Analysis:"
|
|
||||||
echo " Running disk space analysis..."
|
|
||||||
df -h / | tail -1
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 10. Check what macOS Storage Management shows
|
|
||||||
echo "10. System Files Category:"
|
|
||||||
echo " 💡 To see what macOS considers 'System Files':"
|
|
||||||
echo " Apple Menu → About This Mac → Storage → Manage"
|
|
||||||
echo " Look under 'System Files' category"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Summary
|
|
||||||
echo "=== Summary ==="
|
|
||||||
echo ""
|
|
||||||
echo "To find the 100GB+ of Time Machine system files:"
|
|
||||||
echo ""
|
|
||||||
echo "1. Check macOS Storage Management:"
|
|
||||||
echo " Apple Menu → About This Mac → Storage → Manage → System Files"
|
|
||||||
echo ""
|
|
||||||
echo "2. Check for local snapshots (APFS snapshots):"
|
|
||||||
echo " tmutil listlocalsnapshots /"
|
|
||||||
echo " sudo tmutil listlocalsnapshots /"
|
|
||||||
echo ""
|
|
||||||
echo "3. Check MobileBackups:"
|
|
||||||
echo " sudo du -sh /.MobileBackups"
|
|
||||||
echo " sudo du -sh /System/Volumes/Data/.MobileBackups"
|
|
||||||
echo ""
|
|
||||||
echo "4. Find all sparse bundles:"
|
|
||||||
echo " sudo find / -name '*.sparsebundle' -o -name '*.sparseimage' 2>/dev/null"
|
|
||||||
echo ""
|
|
||||||
echo "5. Check system volumes:"
|
|
||||||
echo " sudo du -h -d 1 /System/Volumes/Data | sort -hr | head -20"
|
|
||||||
echo ""
|
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Fix: Free Space After Deleting Files
|
|
||||||
# When you delete files but don't see space back, this script fixes it
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Fix: Free Space After Deleting Files ==="
|
|
||||||
echo ""
|
|
||||||
echo "This script handles the common issue where deleted files don't free up space"
|
|
||||||
echo "because APFS snapshots are holding onto them."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check current free space
|
|
||||||
FREE_SPACE_BEFORE=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB_BEFORE=$(echo "scale=2; $FREE_SPACE_BEFORE / 1024 / 1024" | bc)
|
|
||||||
echo "Current free space: ${FREE_SPACE_GB_BEFORE}GB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check for Time Machine local snapshots
|
|
||||||
echo "📸 Checking for Time Machine local snapshots..."
|
|
||||||
TM_SNAPSHOTS=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$")
|
|
||||||
if [ -n "$TM_SNAPSHOTS" ]; then
|
|
||||||
echo " Found snapshot(s) that may be holding space:"
|
|
||||||
echo "$TM_SNAPSHOTS" | sed 's/^/ - /'
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
read -p "Delete these snapshots to free space? (y/n) " -n 1 -r
|
|
||||||
echo ""
|
|
||||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
||||||
echo ""
|
|
||||||
echo "🗑️ Deleting snapshots..."
|
|
||||||
|
|
||||||
# Disable local snapshots first (helps with stuck snapshots)
|
|
||||||
echo " 1. Disabling local snapshots..."
|
|
||||||
sudo tmutil disablelocal 2>/dev/null || true
|
|
||||||
sleep 2
|
|
||||||
|
|
||||||
# Delete each snapshot
|
|
||||||
echo " 2. Deleting snapshots..."
|
|
||||||
echo "$TM_SNAPSHOTS" | while read snapshot; do
|
|
||||||
if [ -n "$snapshot" ]; then
|
|
||||||
# Extract date part from snapshot name
|
|
||||||
SNAP_DATE=$(echo "$snapshot" | sed 's/.*\.\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}\)\.backup/\1/')
|
|
||||||
if [ -n "$SNAP_DATE" ]; then
|
|
||||||
echo " Deleting: $snapshot"
|
|
||||||
sudo tmutil deletelocalsnapshots "$SNAP_DATE" 2>/dev/null && \
|
|
||||||
echo " ✓ Deleted" || \
|
|
||||||
echo " ⚠️ Could not delete (may need restart)"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# Try to thin all snapshots
|
|
||||||
echo " 3. Thinning all local snapshots..."
|
|
||||||
sudo tmutil thinlocalsnapshots / 1000000000 4 2>/dev/null || true
|
|
||||||
|
|
||||||
# Re-enable local snapshots
|
|
||||||
echo " 4. Re-enabling local snapshots..."
|
|
||||||
sleep 2
|
|
||||||
sudo tmutil enablelocal 2>/dev/null || true
|
|
||||||
|
|
||||||
echo " ✓ Snapshot cleanup completed"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo " ✓ No Time Machine snapshots found"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Force purge of memory and disk caches
|
|
||||||
echo "🧹 Purging system caches..."
|
|
||||||
if command -v purge &> /dev/null; then
|
|
||||||
sudo purge
|
|
||||||
echo " ✓ Purge completed"
|
|
||||||
else
|
|
||||||
echo " ⚠️ Purge command not available"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Wait a moment for system to update
|
|
||||||
echo "⏳ Waiting for system to update disk space..."
|
|
||||||
sleep 5
|
|
||||||
|
|
||||||
# Check new free space
|
|
||||||
FREE_SPACE_AFTER=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB_AFTER=$(echo "scale=2; $FREE_SPACE_AFTER / 1024 / 1024" | bc)
|
|
||||||
FREED_GB=$(echo "scale=2; $FREE_SPACE_GB_AFTER - $FREE_SPACE_GB_BEFORE" | bc)
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "=== Results ==="
|
|
||||||
echo " Before: ${FREE_SPACE_GB_BEFORE}GB free"
|
|
||||||
echo " After: ${FREE_SPACE_GB_AFTER}GB free"
|
|
||||||
if (( $(echo "$FREED_GB > 0" | bc -l) )); then
|
|
||||||
echo " ✅ Freed: ${FREED_GB}GB"
|
|
||||||
else
|
|
||||||
echo " ⚠️ No space freed yet"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
if (( $(echo "$FREED_GB < 15" | bc -l) )) && (( $(echo "$FREE_SPACE_GB_AFTER < 5" | bc -l) )); then
|
|
||||||
echo "⚠️ If space still not freed, try these steps:"
|
|
||||||
echo ""
|
|
||||||
echo "1. **Restart your Mac** - This is often the most effective solution."
|
|
||||||
echo " Snapshots are sometimes only released after a restart."
|
|
||||||
echo ""
|
|
||||||
echo "2. Check if Time Machine is trying to connect:"
|
|
||||||
echo " - Open System Settings → Time Machine"
|
|
||||||
echo " - If it says 'Connecting...', wait for it to finish or disconnect"
|
|
||||||
echo " - Then try deleting snapshots again"
|
|
||||||
echo ""
|
|
||||||
echo "3. Manually delete the snapshot after disabling Time Machine:"
|
|
||||||
echo " sudo tmutil disablelocal"
|
|
||||||
echo " sudo tmutil deletelocalsnapshots <date>"
|
|
||||||
echo " sudo tmutil enablelocal"
|
|
||||||
echo ""
|
|
||||||
echo "4. Use macOS Storage Management:"
|
|
||||||
echo " Apple Menu → About This Mac → Storage → Manage"
|
|
||||||
echo " This tool can identify and remove large system files"
|
|
||||||
echo ""
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Fix Oracle server firewall for WireGuard forwarding
|
|
||||||
echo "Fixing Oracle server firewall rules..."
|
|
||||||
|
|
||||||
ssh server2 "sudo iptables -I FORWARD -i wg0 -j ACCEPT"
|
|
||||||
ssh server2 "sudo iptables -I FORWARD -o wg0 -j ACCEPT"
|
|
||||||
ssh server2 "sudo iptables -I FORWARD -s 10.0.0.0/24 -d 192.168.1.0/24 -j ACCEPT"
|
|
||||||
|
|
||||||
echo "Firewall rules applied successfully!"
|
|
||||||
echo "Test connection: curl -I http://192.168.1.172:5000/"
|
|
||||||
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# Fix iPhone Mirroring connection issues
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "🔧 Fixing iPhone Mirroring issues..."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check macOS version
|
|
||||||
echo "📱 Checking macOS version..."
|
|
||||||
MACOS_VERSION=$(sw_vers -productVersion | cut -d. -f1)
|
|
||||||
if [ "$MACOS_VERSION" -lt 15 ]; then
|
|
||||||
echo "❌ Error: iPhone Mirroring requires macOS Sequoia 15.0 or later"
|
|
||||||
echo " Current version: $(sw_vers -productVersion)"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
echo "✅ macOS version OK: $(sw_vers -productVersion)"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Enable Handoff/Continuity
|
|
||||||
echo "🔄 Enabling Handoff and Continuity features..."
|
|
||||||
defaults write com.apple.coreservices.useractivityd.plist ActivityAdvertisingAllowed -bool true
|
|
||||||
defaults write com.apple.coreservices.useractivityd.plist ActivityReceivingAllowed -bool true
|
|
||||||
echo "✅ Handoff enabled"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Restart Continuity services
|
|
||||||
echo "🔄 Restarting Continuity services..."
|
|
||||||
killall sharingd 2>/dev/null || true
|
|
||||||
killall bluetoothd 2>/dev/null || true
|
|
||||||
sleep 2
|
|
||||||
|
|
||||||
# Restart Bluetooth daemon
|
|
||||||
echo "🔄 Restarting Bluetooth..."
|
|
||||||
sudo launchctl stop com.apple.bluetoothd 2>/dev/null || true
|
|
||||||
sleep 1
|
|
||||||
sudo launchctl start com.apple.bluetoothd 2>/dev/null || true
|
|
||||||
echo "✅ Services restarted"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check Bluetooth and Wi-Fi status
|
|
||||||
echo "📡 Checking connectivity..."
|
|
||||||
BLUETOOTH_STATUS=$(system_profiler SPBluetoothDataType 2>/dev/null | grep -i "state" | head -1 | grep -i "on" && echo "On" || echo "Off")
|
|
||||||
WIFI_STATUS=$(networksetup -getairportpower en0 2>/dev/null | grep -i "on" && echo "On" || echo "Off")
|
|
||||||
|
|
||||||
if [ "$BLUETOOTH_STATUS" = "On" ]; then
|
|
||||||
echo "✅ Bluetooth is enabled"
|
|
||||||
else
|
|
||||||
echo "⚠️ Bluetooth is disabled - please enable it in System Settings"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$WIFI_STATUS" = "On" ]; then
|
|
||||||
echo "✅ Wi-Fi is enabled"
|
|
||||||
else
|
|
||||||
echo "⚠️ Wi-Fi is disabled - please enable it in System Settings"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Verify Handoff settings
|
|
||||||
echo "✅ Verifying Handoff settings..."
|
|
||||||
ADVERTISING=$(defaults read com.apple.coreservices.useractivityd.plist ActivityAdvertisingAllowed 2>/dev/null || echo "false")
|
|
||||||
RECEIVING=$(defaults read com.apple.coreservices.useractivityd.plist ActivityReceivingAllowed 2>/dev/null || echo "false")
|
|
||||||
|
|
||||||
if [ "$ADVERTISING" = "1" ] && [ "$RECEIVING" = "1" ]; then
|
|
||||||
echo "✅ Handoff is properly configured"
|
|
||||||
else
|
|
||||||
echo "❌ Handoff configuration incomplete"
|
|
||||||
echo " ActivityAdvertisingAllowed: $ADVERTISING"
|
|
||||||
echo " ActivityReceivingAllowed: $RECEIVING"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
||||||
echo "✅ Fix script completed!"
|
|
||||||
echo ""
|
|
||||||
echo "📋 Next steps:"
|
|
||||||
echo " 1. Make sure your iPhone is:"
|
|
||||||
echo " - Running iOS 18.0 or later"
|
|
||||||
echo " - Unlocked and near this Mac"
|
|
||||||
echo " - Signed in to the SAME iCloud account"
|
|
||||||
echo " - Has Bluetooth and Wi-Fi enabled"
|
|
||||||
echo ""
|
|
||||||
echo " 2. Restart your Mac (recommended):"
|
|
||||||
echo " sudo reboot"
|
|
||||||
echo ""
|
|
||||||
echo " 3. After restart, try iPhone Mirroring again"
|
|
||||||
echo ""
|
|
||||||
echo " 4. If still not working, check:"
|
|
||||||
echo " - System Settings → General → AirDrop & Handoff"
|
|
||||||
echo " → Ensure 'Handoff' is enabled"
|
|
||||||
echo " - System Settings → Privacy & Security → Bluetooth"
|
|
||||||
echo " → Ensure Bluetooth access is granted"
|
|
||||||
echo " - System Settings → Network → Firewall"
|
|
||||||
echo " → Temporarily disable to test"
|
|
||||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
# Fix Network Security Group (NSG) Rules
|
|
||||||
|
|
||||||
## The Problem
|
|
||||||
Your instance has a **Network Security Group (NSG)** called `ig-quick-action-NSG` that might be blocking traffic even though Security List rules are added.
|
|
||||||
|
|
||||||
Oracle Cloud has **two firewall layers**:
|
|
||||||
1. **Security Lists** (VCN level) - ✅ You added rules here
|
|
||||||
2. **Network Security Groups (NSG)** (Instance level) - ❌ Might be blocking!
|
|
||||||
|
|
||||||
## Solution: Add Rules to NSG
|
|
||||||
|
|
||||||
### Step 1: Go to Network Security Group
|
|
||||||
From your instance details page (where you saw the VNIC info):
|
|
||||||
|
|
||||||
1. Find **"Network security groups"** section
|
|
||||||
2. Click on **"ig-quick-action-NSG"** (the blue link)
|
|
||||||
3. This opens the NSG details page
|
|
||||||
|
|
||||||
### Step 2: Add Ingress Rules
|
|
||||||
1. Click on **"Ingress Rules"** tab
|
|
||||||
2. Click **"Add Ingress Rules"**
|
|
||||||
3. Add the same 4 rules:
|
|
||||||
|
|
||||||
**Rule 1:**
|
|
||||||
- Source Type: CIDR
|
|
||||||
- Source CIDR: `0.0.0.0/0`
|
|
||||||
- IP Protocol: TCP
|
|
||||||
- Destination Port Range: `7890`
|
|
||||||
- Description: `Clash HTTP Proxy`
|
|
||||||
|
|
||||||
**Rule 2:**
|
|
||||||
- Source Type: CIDR
|
|
||||||
- Source CIDR: `0.0.0.0/0`
|
|
||||||
- IP Protocol: TCP
|
|
||||||
- Destination Port Range: `7891`
|
|
||||||
- Description: `Clash SOCKS5`
|
|
||||||
|
|
||||||
**Rule 3:**
|
|
||||||
- Source Type: CIDR
|
|
||||||
- Source CIDR: `0.0.0.0/0`
|
|
||||||
- IP Protocol: TCP
|
|
||||||
- Destination Port Range: `7892`
|
|
||||||
- Description: `Clash Mixed`
|
|
||||||
|
|
||||||
**Rule 4:**
|
|
||||||
- Source Type: CIDR
|
|
||||||
- Source CIDR: `0.0.0.0/0`
|
|
||||||
- IP Protocol: TCP
|
|
||||||
- Destination Port Range: `9090`
|
|
||||||
- Description: `Clash Web UI`
|
|
||||||
|
|
||||||
### Step 3: Save and Test
|
|
||||||
1. Click **"Add Ingress Rules"**
|
|
||||||
2. Wait 30-60 seconds
|
|
||||||
3. Test again: `curl --proxy http://proxy_user:Cs7yBx1Rh9oK@158.101.140.85:7890 http://httpbin.org/ip`
|
|
||||||
|
|
||||||
## Alternative: Remove NSG (If Not Needed)
|
|
||||||
|
|
||||||
If you don't need the NSG:
|
|
||||||
1. Go to instance → Primary VNIC
|
|
||||||
2. Click **"Edit"** next to Network security groups
|
|
||||||
3. Remove `ig-quick-action-NSG`
|
|
||||||
4. Save
|
|
||||||
|
|
||||||
Then Security List rules will be enough.
|
|
||||||
|
|
||||||
## Quick Path
|
|
||||||
```
|
|
||||||
Instance Details → Primary VNIC → Network security groups → ig-quick-action-NSG → Ingress Rules → Add Ingress Rules
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
# Fix Oracle Cloud Firewall for Proxy
|
|
||||||
|
|
||||||
## The Problem
|
|
||||||
Connection times out because **Oracle Cloud Security List** is blocking the ports, even though UFW allows them.
|
|
||||||
|
|
||||||
## Solution: Add Security List Rules in Oracle Cloud
|
|
||||||
|
|
||||||
### Method 1: Via Web Console (Easiest)
|
|
||||||
|
|
||||||
1. **Log into Oracle Cloud Console**
|
|
||||||
- Go to: https://cloud.oracle.com
|
|
||||||
- Navigate to your instance
|
|
||||||
|
|
||||||
2. **Find Your VCN/Subnet:**
|
|
||||||
- Go to **Networking** → **Virtual Cloud Networks**
|
|
||||||
- Click on your VCN
|
|
||||||
- Click on your **Subnet**
|
|
||||||
|
|
||||||
3. **Edit Security List:**
|
|
||||||
- Click on **Security Lists** tab
|
|
||||||
- Click on the default security list (or the one attached to your subnet)
|
|
||||||
- Click **Edit All Rules**
|
|
||||||
|
|
||||||
4. **Add Ingress Rules:**
|
|
||||||
Click **Add Ingress Rules** for each port:
|
|
||||||
|
|
||||||
**Rule 1: HTTP Proxy (7890)**
|
|
||||||
- **Source Type:** CIDR
|
|
||||||
- **Source CIDR:** `0.0.0.0/0` (or your IP for security)
|
|
||||||
- **IP Protocol:** TCP
|
|
||||||
- **Destination Port Range:** `7890`
|
|
||||||
- **Description:** Clash HTTP Proxy
|
|
||||||
|
|
||||||
**Rule 2: SOCKS5 Proxy (7891)**
|
|
||||||
- **Source Type:** CIDR
|
|
||||||
- **Source CIDR:** `0.0.0.0/0`
|
|
||||||
- **IP Protocol:** TCP
|
|
||||||
- **Destination Port Range:** `7891`
|
|
||||||
- **Description:** Clash SOCKS5 Proxy
|
|
||||||
|
|
||||||
**Rule 3: Mixed Proxy (7892)**
|
|
||||||
- **Source Type:** CIDR
|
|
||||||
- **Source CIDR:** `0.0.0.0/0`
|
|
||||||
- **IP Protocol:** TCP
|
|
||||||
- **Destination Port Range:** `7892`
|
|
||||||
- **Description:** Clash Mixed Proxy
|
|
||||||
|
|
||||||
**Rule 4: Web UI (9090)**
|
|
||||||
- **Source Type:** CIDR
|
|
||||||
- **Source CIDR:** `0.0.0.0/0`
|
|
||||||
- **IP Protocol:** TCP
|
|
||||||
- **Destination Port Range:** `9090`
|
|
||||||
- **Description:** Clash Web UI
|
|
||||||
|
|
||||||
5. **Save** the rules
|
|
||||||
|
|
||||||
6. **Wait 30 seconds** for rules to propagate
|
|
||||||
|
|
||||||
7. **Test again** from your iPhone
|
|
||||||
|
|
||||||
### Method 2: Via OCI CLI
|
|
||||||
|
|
||||||
If you have OCI CLI installed:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Get your security list OCID
|
|
||||||
oci network security-list list --compartment-id <your-compartment-id>
|
|
||||||
|
|
||||||
# Add ingress rule
|
|
||||||
oci network security-list update \
|
|
||||||
--security-list-id <your-security-list-id> \
|
|
||||||
--ingress-security-rules file://ingress-rules.json
|
|
||||||
```
|
|
||||||
|
|
||||||
### Security Note
|
|
||||||
|
|
||||||
Using `0.0.0.0/0` allows access from anywhere. For better security:
|
|
||||||
- Use your home IP: `YOUR_IP/32`
|
|
||||||
- Or use a VPN IP range
|
|
||||||
- The proxy has authentication, so it's somewhat protected
|
|
||||||
|
|
||||||
## Verify Rules Are Applied
|
|
||||||
|
|
||||||
After adding rules, test:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# From your Mac (not iPhone)
|
|
||||||
nc -zv 158.101.140.85 7890
|
|
||||||
# Should show: Connection succeeded
|
|
||||||
```
|
|
||||||
|
|
||||||
## Alternative: Use Tailscale Instead
|
|
||||||
|
|
||||||
If you don't want to open ports publicly:
|
|
||||||
- Keep proxy on Tailscale IP only (100.70.115.1)
|
|
||||||
- Use Tailscale VPN on iPhone
|
|
||||||
- Access proxy via Tailscale network
|
|
||||||
|
|
||||||
But this requires Tailscale VPN, which conflicts with Shadowrocket VPN.
|
|
||||||
|
|
||||||
## Quick Checklist
|
|
||||||
|
|
||||||
- [ ] Logged into Oracle Cloud Console
|
|
||||||
- [ ] Found VCN and Subnet
|
|
||||||
- [ ] Opened Security List
|
|
||||||
- [ ] Added ingress rules for ports 7890, 7891, 7892, 9090
|
|
||||||
- [ ] Saved rules
|
|
||||||
- [ ] Waited 30 seconds
|
|
||||||
- [ ] Tested from iPhone
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Fix OS Update Snapshot Issue (351GB System Data)
|
|
||||||
# The OS update snapshot is preventing space from being freed
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Fix OS Update Snapshot Issue ==="
|
|
||||||
echo ""
|
|
||||||
echo "Your disk layout shows:"
|
|
||||||
echo " - Container: 494.4 GB"
|
|
||||||
echo " - Data volume: 472.5 GB"
|
|
||||||
echo " - System volume: 12.2 GB"
|
|
||||||
echo " - OS Update Snapshot: 12.2 GB (NOT purgeable)"
|
|
||||||
echo ""
|
|
||||||
echo "The 351GB in System Data is likely snapshot overhead"
|
|
||||||
echo "that can't be freed until the snapshot is cleared."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
FREE_SPACE_BEFORE=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB_BEFORE=$(echo "scale=2; $FREE_SPACE_BEFORE / 1024 / 1024" | bc)
|
|
||||||
echo "Current free space: ${FREE_SPACE_GB_BEFORE}GB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🔍 Checking for macOS updates..."
|
|
||||||
UPDATES=$(softwareupdate --list 2>/dev/null | grep -i "update" | head -5)
|
|
||||||
if [ -n "$UPDATES" ]; then
|
|
||||||
echo " Found available updates:"
|
|
||||||
echo "$UPDATES" | sed 's/^/ /'
|
|
||||||
echo ""
|
|
||||||
echo " ✅ SOLUTION: Install macOS updates"
|
|
||||||
echo " This will create a new snapshot and clear the old one"
|
|
||||||
echo " System Settings → General → Software Update"
|
|
||||||
else
|
|
||||||
echo " No updates found (or check failed)"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🔧 Immediate Space Savings:"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check macOS Install Data
|
|
||||||
INSTALL_DATA="/System/Volumes/Data/macOS Install Data"
|
|
||||||
if [ -d "$INSTALL_DATA" ]; then
|
|
||||||
SIZE=$(sudo du -sh "$INSTALL_DATA" 2>/dev/null | awk '{print $1}')
|
|
||||||
echo " 1. Delete macOS Install Data: $SIZE"
|
|
||||||
echo " sudo rm -rf \"$INSTALL_DATA\""
|
|
||||||
echo " (Safe to delete after installation completes)"
|
|
||||||
echo ""
|
|
||||||
read -p " Delete macOS Install Data now? (y/n) " -n 1 -r
|
|
||||||
echo ""
|
|
||||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
||||||
echo " Deleting..."
|
|
||||||
sudo rm -rf "$INSTALL_DATA" 2>/dev/null && \
|
|
||||||
echo " ✅ Deleted ($SIZE freed)" || \
|
|
||||||
echo " ⚠️ Could not delete (may be in use)"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo " 1. macOS Install Data: Not found"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "📊 Understanding the Problem:"
|
|
||||||
echo ""
|
|
||||||
echo "The OS update snapshot (12.2GB visible) is holding much more"
|
|
||||||
echo "space as 'overhead' or 'purgeable' that shows up in System Data."
|
|
||||||
echo ""
|
|
||||||
echo "APFS snapshots work by:"
|
|
||||||
echo " - Preserving deleted files"
|
|
||||||
echo " - Taking up space until cleared"
|
|
||||||
echo " - The OS update snapshot can't be deleted manually"
|
|
||||||
echo ""
|
|
||||||
echo "The 351GB in System Data includes:"
|
|
||||||
echo " - Snapshot overhead (space held by the snapshot)"
|
|
||||||
echo " - Purgeable space (that can't be purged due to snapshot)"
|
|
||||||
echo " - System reserved space"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "=== Solutions ==="
|
|
||||||
echo ""
|
|
||||||
echo "Option 1: Install macOS Updates (Recommended)"
|
|
||||||
echo " - System Settings → General → Software Update"
|
|
||||||
echo " - Install any available updates"
|
|
||||||
echo " - This will clear the old snapshot"
|
|
||||||
echo " - Should free the 351GB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "Option 2: Wait for Automatic Cleanup"
|
|
||||||
echo " - macOS may clear old snapshots automatically"
|
|
||||||
echo " - But this can take weeks or months"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "Option 3: Free Other Space First"
|
|
||||||
echo " - Clean Downloads: 8.7GB"
|
|
||||||
echo " - Clean Caches: ~6GB"
|
|
||||||
echo " - Review Documents: 40GB"
|
|
||||||
echo " - This gives you ~55GB to work with"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "Option 4: Check Storage Management Details"
|
|
||||||
echo " - Apple Menu → About This Mac → Storage"
|
|
||||||
echo " - Hover over 'System Data' for breakdown"
|
|
||||||
echo " - May show 'Purgeable' or 'Snapshots'"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check final space
|
|
||||||
sleep 2
|
|
||||||
FREE_SPACE_AFTER=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB_AFTER=$(echo "scale=2; $FREE_SPACE_AFTER / 1024 / 1024" | bc)
|
|
||||||
FREED_GB=$(echo "scale=2; $FREE_SPACE_GB_AFTER - $FREE_SPACE_GB_BEFORE" | bc)
|
|
||||||
|
|
||||||
if (( $(echo "$FREED_GB > 0" | bc -l) )); then
|
|
||||||
echo "✅ Freed: ${FREED_GB}GB"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Fix Photo Volume Taking 175GB
|
|
||||||
# This is likely a mounted volume or disk image
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Fix Photo Volume (175GB) ==="
|
|
||||||
echo ""
|
|
||||||
echo "Found: /System/Volumes/Data/Volumes/photo is 175GB!"
|
|
||||||
echo "This is likely what's consuming your space."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check what it is
|
|
||||||
echo "🔍 Checking what 'photo' is:"
|
|
||||||
if [ -d "/System/Volumes/Data/Volumes/photo" ]; then
|
|
||||||
echo " It's a directory"
|
|
||||||
SIZE=$(sudo du -sh /System/Volumes/Data/Volumes/photo 2>/dev/null | awk '{print $1}')
|
|
||||||
echo " Size: $SIZE"
|
|
||||||
|
|
||||||
# Check if it's mounted
|
|
||||||
MOUNTED=$(mount | grep photo || echo "NOT_MOUNTED")
|
|
||||||
if [ "$MOUNTED" != "NOT_MOUNTED" ]; then
|
|
||||||
echo " ⚠️ It's a MOUNTED volume:"
|
|
||||||
echo "$MOUNTED" | sed 's/^/ /'
|
|
||||||
echo ""
|
|
||||||
echo " This is likely a disk image or network mount."
|
|
||||||
echo " You can unmount it to free the space."
|
|
||||||
else
|
|
||||||
echo " It's a regular directory (not mounted)"
|
|
||||||
echo " Contents:"
|
|
||||||
ls -lah /System/Volumes/Data/Volumes/photo 2>/dev/null | head -10 | sed 's/^/ /'
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo " Not found or not accessible"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check if it's safe to remove
|
|
||||||
echo "❓ Questions:"
|
|
||||||
echo " 1. Do you have a 'photo' volume mounted?"
|
|
||||||
echo " 2. Is this from an external drive or disk image?"
|
|
||||||
echo " 3. Do you need this data?"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🔧 Solutions:"
|
|
||||||
echo ""
|
|
||||||
echo "If it's a mounted volume you don't need:"
|
|
||||||
echo " sudo umount /System/Volumes/Data/Volumes/photo"
|
|
||||||
echo ""
|
|
||||||
echo "If it's a directory with files you don't need:"
|
|
||||||
echo " sudo rm -rf /System/Volumes/Data/Volumes/photo/*"
|
|
||||||
echo ""
|
|
||||||
echo "⚠️ WARNING: Make sure you don't need this data before deleting!"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
read -p "Do you want to see what's inside? (y/n) " -n 1 -r
|
|
||||||
echo ""
|
|
||||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
||||||
echo ""
|
|
||||||
echo "📁 Contents of /System/Volumes/Data/Volumes/photo:"
|
|
||||||
sudo ls -lah /System/Volumes/Data/Volumes/photo 2>/dev/null | head -20 | sed 's/^/ /'
|
|
||||||
echo ""
|
|
||||||
echo "📊 Top subdirectories:"
|
|
||||||
sudo du -h -d 1 /System/Volumes/Data/Volumes/photo 2>/dev/null | sort -hr | head -10 | awk '{printf " %8s %s\n", $1, $2}'
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Fix QuickConnect 502 Error
|
|
||||||
# HTTP ERROR 502 - Bad Gateway
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Fix QuickConnect 502 Error ==="
|
|
||||||
echo ""
|
|
||||||
echo "502 Bad Gateway means QuickConnect relay server"
|
|
||||||
echo "can't reach your NAS or NAS is having issues."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🔍 Diagnosing..."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check local network connectivity
|
|
||||||
echo "1. Checking local network connection..."
|
|
||||||
if ping -c 2 DS224plus.local &>/dev/null || ping -c 2 192.168.1.172 &>/dev/null; then
|
|
||||||
echo " ✅ NAS is reachable on local network"
|
|
||||||
LOCAL_REACHABLE=true
|
|
||||||
else
|
|
||||||
echo " ❌ NAS not reachable on local network"
|
|
||||||
LOCAL_REACHABLE=false
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check SSH access
|
|
||||||
echo "2. Checking SSH access..."
|
|
||||||
if nas "uptime" &>/dev/null; then
|
|
||||||
echo " ✅ Can connect via SSH"
|
|
||||||
SSH_WORKING=true
|
|
||||||
else
|
|
||||||
echo " ❌ Cannot connect via SSH"
|
|
||||||
SSH_WORKING=false
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check DSM web interface locally
|
|
||||||
echo "3. Checking DSM web interface (local)..."
|
|
||||||
HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 http://192.168.1.172:5000 2>/dev/null || echo "000")
|
|
||||||
if [ "$HTTP_STATUS" = "200" ] || [ "$HTTP_STATUS" = "302" ]; then
|
|
||||||
echo " ✅ DSM web interface working locally"
|
|
||||||
WEB_WORKING=true
|
|
||||||
else
|
|
||||||
echo " ❌ DSM web interface not responding (HTTP $HTTP_STATUS)"
|
|
||||||
WEB_WORKING=false
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "=== Solutions ==="
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
if [ "$LOCAL_REACHABLE" = true ] && [ "$WEB_WORKING" = true ]; then
|
|
||||||
echo "✅ NAS is working locally!"
|
|
||||||
echo ""
|
|
||||||
echo "The 502 error is a QuickConnect issue, not your NAS."
|
|
||||||
echo ""
|
|
||||||
echo "Solution: Use local access instead:"
|
|
||||||
echo ""
|
|
||||||
echo " http://192.168.1.172:5000"
|
|
||||||
echo " or"
|
|
||||||
echo " http://DS224plus.local:5000"
|
|
||||||
echo ""
|
|
||||||
echo "QuickConnect issues are usually:"
|
|
||||||
echo " - QuickConnect relay server problems (temporary)"
|
|
||||||
echo " - QuickConnect service disabled on NAS"
|
|
||||||
echo " - Network/firewall blocking QuickConnect"
|
|
||||||
echo ""
|
|
||||||
elif [ "$LOCAL_REACHABLE" = true ] && [ "$SSH_WORKING" = true ]; then
|
|
||||||
echo "✅ NAS is reachable via SSH"
|
|
||||||
echo ""
|
|
||||||
echo "DSM web interface may be down. Check:"
|
|
||||||
echo ""
|
|
||||||
echo " 1. NAS may be restarting or updating"
|
|
||||||
echo " 2. Web service may be stopped"
|
|
||||||
echo ""
|
|
||||||
echo "Via SSH, check:"
|
|
||||||
echo " nas 'synoservice --status nginx'"
|
|
||||||
echo " nas 'synoservice --status httpd-user'"
|
|
||||||
echo ""
|
|
||||||
else
|
|
||||||
echo "⚠️ NAS may be down or unreachable"
|
|
||||||
echo ""
|
|
||||||
echo "Check:"
|
|
||||||
echo " 1. Is NAS powered on? (Check power LED)"
|
|
||||||
echo " 2. Is NAS connected to network? (Check network LED)"
|
|
||||||
echo " 3. Try accessing directly: http://192.168.1.172:5000"
|
|
||||||
echo ""
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "=== QuickConnect 502 Error Fixes ==="
|
|
||||||
echo ""
|
|
||||||
echo "1. **Use Local Access Instead** (Recommended)"
|
|
||||||
echo " http://192.168.1.172:5000"
|
|
||||||
echo " This bypasses QuickConnect entirely"
|
|
||||||
echo ""
|
|
||||||
echo "2. **Check QuickConnect Settings**"
|
|
||||||
echo " If you can access NAS locally:"
|
|
||||||
echo " - Control Panel → External Access → QuickConnect"
|
|
||||||
echo " - Make sure QuickConnect is enabled"
|
|
||||||
echo " - Try disabling and re-enabling"
|
|
||||||
echo ""
|
|
||||||
echo "3. **Wait and Retry**"
|
|
||||||
echo " QuickConnect 502 errors are often temporary"
|
|
||||||
echo " Wait 5-10 minutes and try again"
|
|
||||||
echo ""
|
|
||||||
echo "4. **Check NAS Status**"
|
|
||||||
echo " - Is NAS powered on?"
|
|
||||||
echo " - Are status LEDs normal?"
|
|
||||||
echo " - Try restarting NAS if needed"
|
|
||||||
echo ""
|
|
||||||
@@ -1,126 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Fix Stuck Time Machine Backup
|
|
||||||
# When Time Machine is stuck trying to connect to NAS and consuming space
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Fix Stuck Time Machine Backup ==="
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check Time Machine status
|
|
||||||
TM_STATUS=$(tmutil status 2>/dev/null)
|
|
||||||
echo "📊 Current Time Machine Status:"
|
|
||||||
echo "$TM_STATUS" | grep -E "BackupPhase|Running" | sed 's/^/ /'
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check if it's stuck
|
|
||||||
if echo "$TM_STATUS" | grep -q "Running = 1"; then
|
|
||||||
PHASE=$(echo "$TM_STATUS" | grep "BackupPhase" | sed 's/.*BackupPhase = \([^;]*\).*/\1/')
|
|
||||||
echo "⚠️ Time Machine is RUNNING and stuck in phase: $PHASE"
|
|
||||||
echo ""
|
|
||||||
echo " This is why your space disappeared:"
|
|
||||||
echo " - Time Machine created a local snapshot before backing up"
|
|
||||||
echo " - It's trying to connect to NAS but can't"
|
|
||||||
echo " - The snapshot is holding your deleted file space"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check current free space
|
|
||||||
FREE_SPACE=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB=$(echo "scale=2; $FREE_SPACE / 1024 / 1024" | bc)
|
|
||||||
echo " Current free space: ${FREE_SPACE_GB}GB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
read -p "Stop the stuck Time Machine backup? (y/n) " -n 1 -r
|
|
||||||
echo ""
|
|
||||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
||||||
echo ""
|
|
||||||
echo "🛑 Stopping Time Machine backup..."
|
|
||||||
|
|
||||||
# Stop the backup
|
|
||||||
sudo tmutil stopbackup 2>/dev/null || {
|
|
||||||
echo " ⚠️ Could not stop via tmutil, trying alternative method..."
|
|
||||||
# Kill the backupd process (more aggressive)
|
|
||||||
sudo killall backupd 2>/dev/null || true
|
|
||||||
sleep 2
|
|
||||||
}
|
|
||||||
|
|
||||||
echo " ✓ Backup stopped"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Wait a moment
|
|
||||||
echo "⏳ Waiting for processes to clean up..."
|
|
||||||
sleep 5
|
|
||||||
|
|
||||||
# Check if it stopped
|
|
||||||
NEW_STATUS=$(tmutil status 2>/dev/null | grep "Running" || echo "Running = 0")
|
|
||||||
if echo "$NEW_STATUS" | grep -q "Running = 0"; then
|
|
||||||
echo " ✅ Time Machine backup stopped"
|
|
||||||
else
|
|
||||||
echo " ⚠️ Backup may still be running, may need to restart"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Now try to delete the snapshot
|
|
||||||
echo "🗑️ Attempting to delete local snapshot..."
|
|
||||||
SNAPSHOTS=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$")
|
|
||||||
if [ -n "$SNAPSHOTS" ]; then
|
|
||||||
echo "$SNAPSHOTS" | while read snapshot; do
|
|
||||||
if [ -n "$snapshot" ]; then
|
|
||||||
SNAP_DATE=$(echo "$snapshot" | sed 's/.*\.\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}\)\.backup/\1/')
|
|
||||||
if [ -n "$SNAP_DATE" ]; then
|
|
||||||
echo " Deleting: $snapshot"
|
|
||||||
if sudo tmutil deletelocalsnapshots "$SNAP_DATE" 2>/dev/null; then
|
|
||||||
echo " ✅ Snapshot deleted!"
|
|
||||||
else
|
|
||||||
echo " ⚠️ Still stuck - may need to remove Time Machine destination first"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "📊 Checking disk space..."
|
|
||||||
sleep 3
|
|
||||||
NEW_FREE=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
NEW_FREE_GB=$(echo "scale=2; $NEW_FREE / 1024 / 1024" | bc)
|
|
||||||
FREED_GB=$(echo "scale=2; $NEW_FREE_GB - $FREE_SPACE_GB" | bc)
|
|
||||||
|
|
||||||
echo " Before: ${FREE_SPACE_GB}GB free"
|
|
||||||
echo " After: ${NEW_FREE_GB}GB free"
|
|
||||||
if (( $(echo "$FREED_GB > 0" | bc -l) )); then
|
|
||||||
echo " ✅ Freed: ${FREED_GB}GB"
|
|
||||||
else
|
|
||||||
echo " ⚠️ Space not freed yet"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "=== Next Steps ==="
|
|
||||||
echo ""
|
|
||||||
echo "1. If space is still not freed, remove Time Machine destination:"
|
|
||||||
echo " System Settings → Time Machine → Remove backup disk"
|
|
||||||
echo " Then delete snapshot: sudo tmutil deletelocalsnapshots <date>"
|
|
||||||
echo ""
|
|
||||||
echo "2. Fix Time Machine connection issue:"
|
|
||||||
echo " See: time_machine_troubleshooting.md"
|
|
||||||
echo " Common fixes:"
|
|
||||||
echo " - Clear credentials in Keychain Access"
|
|
||||||
echo " - Unmount any manual mounts"
|
|
||||||
echo " - Re-add Time Machine destination"
|
|
||||||
echo ""
|
|
||||||
echo "3. After fixing connection, re-add Time Machine:"
|
|
||||||
echo " System Settings → Time Machine → Add Backup Disk"
|
|
||||||
echo ""
|
|
||||||
else
|
|
||||||
echo "Cancelled."
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "✅ Time Machine is not running"
|
|
||||||
echo ""
|
|
||||||
echo "If space is still missing, check for snapshots:"
|
|
||||||
echo " tmutil listlocalsnapshots /"
|
|
||||||
echo ""
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Fix Stuck Time Machine Snapshot
|
|
||||||
# When snapshots can't be deleted due to "Stale NFS file handle" error
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Fix Stuck Time Machine Snapshot ==="
|
|
||||||
echo ""
|
|
||||||
echo "This script fixes the 'Stale NFS file handle' error that prevents"
|
|
||||||
echo "snapshot deletion. This happens when Time Machine has a stale"
|
|
||||||
echo "connection to the backup destination."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check current situation
|
|
||||||
echo "📊 Current Status:"
|
|
||||||
FREE_SPACE=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB=$(echo "scale=2; $FREE_SPACE / 1024 / 1024" | bc)
|
|
||||||
echo " Free space: ${FREE_SPACE_GB}GB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
SNAPSHOTS=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$")
|
|
||||||
if [ -n "$SNAPSHOTS" ]; then
|
|
||||||
echo " Stuck snapshots found:"
|
|
||||||
echo "$SNAPSHOTS" | sed 's/^/ - /'
|
|
||||||
else
|
|
||||||
echo " ✓ No snapshots found"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "🔧 Solution: Temporarily remove Time Machine destination, delete snapshot, then re-add"
|
|
||||||
echo ""
|
|
||||||
echo "⚠️ IMPORTANT: This will temporarily disconnect Time Machine from your NAS."
|
|
||||||
echo " You'll need to re-add it after the snapshot is deleted."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
read -p "Do you want to proceed? (y/n) " -n 1 -r
|
|
||||||
echo ""
|
|
||||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
||||||
echo "Cancelled."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "Step 1: Removing Time Machine destination..."
|
|
||||||
echo ""
|
|
||||||
echo " Please do this manually:"
|
|
||||||
echo " 1. Open System Settings → General → Time Machine"
|
|
||||||
echo " 2. Click the 'Remove' or '-' button next to your backup disk"
|
|
||||||
echo " 3. Confirm removal"
|
|
||||||
echo ""
|
|
||||||
read -p " Have you removed the Time Machine destination? (y/n) " -n 1 -r
|
|
||||||
echo ""
|
|
||||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
||||||
echo " Please remove it first, then run this script again."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "Step 2: Waiting for Time Machine to disconnect..."
|
|
||||||
sleep 5
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "Step 3: Attempting to delete stuck snapshot..."
|
|
||||||
echo "$SNAPSHOTS" | while read snapshot; do
|
|
||||||
if [ -n "$snapshot" ]; then
|
|
||||||
# Extract date part
|
|
||||||
SNAP_DATE=$(echo "$snapshot" | sed 's/.*\.\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}\)\.backup/\1/')
|
|
||||||
if [ -n "$SNAP_DATE" ]; then
|
|
||||||
echo " Deleting: $snapshot"
|
|
||||||
if sudo tmutil deletelocalsnapshots "$SNAP_DATE" 2>/dev/null; then
|
|
||||||
echo " ✅ Successfully deleted!"
|
|
||||||
else
|
|
||||||
echo " ⚠️ Still stuck. Try restarting your Mac."
|
|
||||||
echo " After restart, run: sudo tmutil deletelocalsnapshots $SNAP_DATE"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "Step 4: Checking disk space..."
|
|
||||||
sleep 3
|
|
||||||
NEW_FREE_SPACE=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
NEW_FREE_SPACE_GB=$(echo "scale=2; $NEW_FREE_SPACE / 1024 / 1024" | bc)
|
|
||||||
FREED_GB=$(echo "scale=2; $NEW_FREE_SPACE_GB - $FREE_SPACE_GB" | bc)
|
|
||||||
|
|
||||||
echo " New free space: ${NEW_FREE_SPACE_GB}GB"
|
|
||||||
if (( $(echo "$FREED_GB > 0" | bc -l) )); then
|
|
||||||
echo " ✅ Freed: ${FREED_GB}GB"
|
|
||||||
else
|
|
||||||
echo " ⚠️ Space not freed yet - may need restart"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "Step 5: Re-adding Time Machine destination..."
|
|
||||||
echo ""
|
|
||||||
echo " Now re-add your Time Machine backup:"
|
|
||||||
echo " 1. System Settings → General → Time Machine"
|
|
||||||
echo " 2. Click 'Add Backup Disk...'"
|
|
||||||
echo " 3. Select 'Time Machine Folder' on 'DS224plus.local'"
|
|
||||||
echo " 4. Enter your credentials"
|
|
||||||
echo ""
|
|
||||||
echo " Or use the troubleshooting guide:"
|
|
||||||
echo " See: time_machine_troubleshooting.md"
|
|
||||||
echo ""
|
|
||||||
@@ -1,161 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Fix System Data Growth When Deleting Files
|
|
||||||
# This happens when APFS snapshots preserve deleted files
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Fix System Data Growth ==="
|
|
||||||
echo ""
|
|
||||||
echo "When you delete files but 'System Data' grows, it means:"
|
|
||||||
echo " - APFS snapshots are preserving deleted files"
|
|
||||||
echo " - Time Machine local snapshots are holding space"
|
|
||||||
echo " - The deleted data is being kept for backup purposes"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
FREE_SPACE_BEFORE=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB_BEFORE=$(echo "scale=2; $FREE_SPACE_BEFORE / 1024 / 1024" | bc)
|
|
||||||
echo "Current free space: ${FREE_SPACE_GB_BEFORE}GB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check for snapshots
|
|
||||||
echo "📸 Checking for snapshots..."
|
|
||||||
TM_SNAPSHOTS=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$")
|
|
||||||
SNAP_COUNT=$(echo "$TM_SNAPSHOTS" | grep -v "^$" | wc -l | tr -d ' ')
|
|
||||||
|
|
||||||
if [ "$SNAP_COUNT" -gt 0 ]; then
|
|
||||||
echo " Found $SNAP_COUNT Time Machine snapshot(s):"
|
|
||||||
echo "$TM_SNAPSHOTS" | sed 's/^/ - /'
|
|
||||||
else
|
|
||||||
echo " No Time Machine snapshots found"
|
|
||||||
fi
|
|
||||||
|
|
||||||
APFS_SNAPS=$(diskutil apfs listSnapshots / 2>/dev/null | grep -c "Name:" || echo "0")
|
|
||||||
echo " Found $APFS_SNAPS APFS snapshot(s)"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
if [ "$SNAP_COUNT" -eq 0 ] && [ "$APFS_SNAPS" -le 1 ]; then
|
|
||||||
echo "⚠️ No obvious snapshots, but System Data is still growing."
|
|
||||||
echo " This may be due to:"
|
|
||||||
echo " - Time Machine preparing for backup"
|
|
||||||
echo " - System cache growth"
|
|
||||||
echo " - Other system processes"
|
|
||||||
echo ""
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "🔧 Solution: Disable local snapshots and clean up"
|
|
||||||
echo ""
|
|
||||||
read -p "Proceed with cleanup? (y/n) " -n 1 -r
|
|
||||||
echo ""
|
|
||||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "Step 1: Stop Time Machine backup (if running)..."
|
|
||||||
sudo tmutil stopbackup 2>/dev/null || true
|
|
||||||
sleep 2
|
|
||||||
echo " ✓ Stopped"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "Step 2: Delete all local snapshots..."
|
|
||||||
if [ "$SNAP_COUNT" -gt 0 ]; then
|
|
||||||
echo "$TM_SNAPSHOTS" | while read snapshot; do
|
|
||||||
if [ -n "$snapshot" ]; then
|
|
||||||
SNAP_DATE=$(echo "$snapshot" | sed 's/.*\.\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}\)\.backup/\1/')
|
|
||||||
if [ -n "$SNAP_DATE" ]; then
|
|
||||||
echo " Deleting: $snapshot"
|
|
||||||
sudo tmutil deletelocalsnapshots "$SNAP_DATE" 2>/dev/null && \
|
|
||||||
echo " ✅ Deleted" || \
|
|
||||||
echo " ⚠️ Could not delete (may be in use)"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
else
|
|
||||||
echo " No snapshots to delete"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "Step 3: Aggressively thin all snapshots..."
|
|
||||||
sudo tmutil thinlocalsnapshots / 1000000000 1 2>&1 || true
|
|
||||||
echo " ✓ Thinned"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "Step 4: Disable local snapshots (prevents new ones)..."
|
|
||||||
# Note: tmutil disablelocal doesn't exist in newer macOS, so we'll use a workaround
|
|
||||||
# We'll remove Time Machine destination temporarily
|
|
||||||
echo " ⚠️ To prevent snapshots, you need to:"
|
|
||||||
echo " 1. Remove Time Machine destination in System Settings"
|
|
||||||
echo " 2. Or wait for successful backup to clear snapshots"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "Step 5: Purge system memory and caches..."
|
|
||||||
if command -v purge &> /dev/null; then
|
|
||||||
sudo purge
|
|
||||||
echo " ✓ Purged"
|
|
||||||
else
|
|
||||||
echo " ⚠️ Purge command not available"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "Step 6: Clean user caches..."
|
|
||||||
rm -rf ~/Library/Caches/* 2>/dev/null || true
|
|
||||||
echo " ✓ Cleaned"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "⏳ Waiting for system to update..."
|
|
||||||
sleep 5
|
|
||||||
|
|
||||||
# Check results
|
|
||||||
FREE_SPACE_AFTER=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB_AFTER=$(echo "scale=2; $FREE_SPACE_AFTER / 1024 / 1024" | bc)
|
|
||||||
FREED_GB=$(echo "scale=2; $FREE_SPACE_GB_AFTER - $FREE_SPACE_GB_BEFORE" | bc)
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "=== Results ==="
|
|
||||||
echo " Before: ${FREE_SPACE_GB_BEFORE}GB free"
|
|
||||||
echo " After: ${FREE_SPACE_GB_AFTER}GB free"
|
|
||||||
if (( $(echo "$FREED_GB > 0" | bc -l) )); then
|
|
||||||
echo " ✅ Freed: ${FREED_GB}GB"
|
|
||||||
else
|
|
||||||
echo " ⚠️ No space freed yet"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "=== Critical Next Steps ==="
|
|
||||||
echo ""
|
|
||||||
echo "To STOP System Data from growing when you delete files:"
|
|
||||||
echo ""
|
|
||||||
echo "1. **Remove Time Machine destination temporarily**:"
|
|
||||||
echo " System Settings → Time Machine → Remove backup disk"
|
|
||||||
echo " This prevents new snapshots from being created"
|
|
||||||
echo ""
|
|
||||||
echo "2. **Wait 10-15 minutes** after deleting files before checking space"
|
|
||||||
echo " macOS needs time to release snapshot space"
|
|
||||||
echo ""
|
|
||||||
echo "3. **After freeing space, fix Time Machine connection**:"
|
|
||||||
echo " - Clear credentials in Keychain Access"
|
|
||||||
echo " - Re-add Time Machine destination"
|
|
||||||
echo " - Ensure it can successfully connect"
|
|
||||||
echo ""
|
|
||||||
echo "4. **Alternative: Use 'Optimize Storage' in System Settings**:"
|
|
||||||
echo " Apple Menu → About This Mac → Storage → Optimize"
|
|
||||||
echo " This can help release snapshot space"
|
|
||||||
echo ""
|
|
||||||
echo "5. **If System Data keeps growing**:"
|
|
||||||
echo " - Restart your Mac (releases snapshots)"
|
|
||||||
echo " - Or remove Time Machine until you have more free space"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
if (( $(echo "$FREE_SPACE_GB_AFTER < 5" | bc -l) )); then
|
|
||||||
echo "⚠️ Still critically low on space!"
|
|
||||||
echo ""
|
|
||||||
echo " You need to free more space before Time Machine can work."
|
|
||||||
echo " Consider:"
|
|
||||||
echo " - Moving large files to NAS"
|
|
||||||
echo " - Removing unused applications"
|
|
||||||
echo " - Cleaning Downloads folder"
|
|
||||||
echo ""
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Quick Fix: Free up space for Time Machine
|
|
||||||
# This script performs safe cleanup operations to free disk space
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Time Machine Disk Space Fix ==="
|
|
||||||
echo ""
|
|
||||||
echo "This script will help free up space so Time Machine can work."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check current free space
|
|
||||||
FREE_SPACE=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB=$(echo "scale=2; $FREE_SPACE / 1024 / 1024" | bc)
|
|
||||||
echo "Current free space: ${FREE_SPACE_GB}GB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Ask for confirmation
|
|
||||||
read -p "Do you want to proceed with safe cleanup? (y/n) " -n 1 -r
|
|
||||||
echo ""
|
|
||||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
||||||
echo "Cancelled."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "🧹 Cleaning up..."
|
|
||||||
|
|
||||||
# 1. Empty Trash
|
|
||||||
if [ -d ~/.Trash ] && [ "$(ls -A ~/.Trash 2>/dev/null)" ]; then
|
|
||||||
TRASH_SIZE=$(du -sh ~/.Trash 2>/dev/null | awk '{print $1}')
|
|
||||||
echo " Emptying Trash ($TRASH_SIZE)..."
|
|
||||||
rm -rf ~/.Trash/* ~/.Trash/.* 2>/dev/null || true
|
|
||||||
echo " ✓ Trash emptied"
|
|
||||||
else
|
|
||||||
echo " ✓ Trash already empty"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 2. Clean Library Caches (safe - will regenerate)
|
|
||||||
if [ -d ~/Library/Caches ]; then
|
|
||||||
CACHES_SIZE=$(du -sh ~/Library/Caches 2>/dev/null | awk '{print $1}')
|
|
||||||
echo " Cleaning Library/Caches ($CACHES_SIZE)..."
|
|
||||||
# Keep some important caches
|
|
||||||
mkdir -p ~/Library/Caches/backup_temp
|
|
||||||
find ~/Library/Caches -mindepth 1 -maxdepth 1 ! -name "backup_temp" -exec mv {} ~/Library/Caches/backup_temp/ \; 2>/dev/null || true
|
|
||||||
rm -rf ~/Library/Caches/backup_temp/* 2>/dev/null || true
|
|
||||||
rmdir ~/Library/Caches/backup_temp 2>/dev/null || true
|
|
||||||
echo " ✓ Caches cleaned"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 3. Clean user cache
|
|
||||||
if [ -d ~/.cache ]; then
|
|
||||||
CACHE_SIZE=$(du -sh ~/.cache 2>/dev/null | awk '{print $1}')
|
|
||||||
echo " Cleaning ~/.cache ($CACHE_SIZE)..."
|
|
||||||
rm -rf ~/.cache/* 2>/dev/null || true
|
|
||||||
echo " ✓ User cache cleaned"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 4. Clean npm cache (if exists)
|
|
||||||
if command -v npm &> /dev/null; then
|
|
||||||
NPM_CACHE_SIZE=$(du -sh ~/.npm 2>/dev/null | awk '{print $1}' || echo "0")
|
|
||||||
if [ "$NPM_CACHE_SIZE" != "0" ] && [ -d ~/.npm ]; then
|
|
||||||
echo " Cleaning npm cache ($NPM_CACHE_SIZE)..."
|
|
||||||
npm cache clean --force 2>/dev/null || true
|
|
||||||
echo " ✓ npm cache cleaned"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "📊 Checking new disk space..."
|
|
||||||
NEW_FREE_SPACE=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
NEW_FREE_SPACE_GB=$(echo "scale=2; $NEW_FREE_SPACE / 1024 / 1024" | bc)
|
|
||||||
FREED_GB=$(echo "scale=2; $NEW_FREE_SPACE_GB - $FREE_SPACE_GB" | bc)
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "=== Results ==="
|
|
||||||
echo " Before: ${FREE_SPACE_GB}GB free"
|
|
||||||
echo " After: ${NEW_FREE_SPACE_GB}GB free"
|
|
||||||
if (( $(echo "$FREED_GB > 0" | bc -l) )); then
|
|
||||||
echo " Freed: ${FREED_GB}GB"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check if we have enough space now
|
|
||||||
if (( $(echo "$NEW_FREE_SPACE_GB < 5" | bc -l) )); then
|
|
||||||
echo "⚠️ Still low on space. Additional recommendations:"
|
|
||||||
echo ""
|
|
||||||
echo " 1. Review Downloads folder (19GB found):"
|
|
||||||
echo " cd ~/Downloads && ls -lhS | head -20"
|
|
||||||
echo ""
|
|
||||||
echo " 2. Check Documents folder (60GB found):"
|
|
||||||
echo " Move large files to NAS if possible"
|
|
||||||
echo ""
|
|
||||||
echo " 3. Review .ollama folder (17GB found):"
|
|
||||||
echo " Consider removing unused models"
|
|
||||||
echo ""
|
|
||||||
echo " 4. Use macOS Storage Management:"
|
|
||||||
echo " Apple Menu → About This Mac → Storage → Manage"
|
|
||||||
echo ""
|
|
||||||
else
|
|
||||||
echo "✅ Good! You should have enough space for Time Machine now."
|
|
||||||
echo " Try running Time Machine backup again."
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Fix Synology USB Copy Issue
|
|
||||||
# Based on diagnosis findings
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Fix Synology USB Copy ==="
|
|
||||||
echo ""
|
|
||||||
echo "Diagnosis found:"
|
|
||||||
echo " - USB connection errors (cable/device issue)"
|
|
||||||
echo " - USB device was unmounted"
|
|
||||||
echo " - No USB device currently mounted"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🔧 Solutions:"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "1. **Physical USB Connection Issue**"
|
|
||||||
echo ""
|
|
||||||
echo " The logs show: 'Cannot enable. Maybe the USB cable is bad?'"
|
|
||||||
echo ""
|
|
||||||
echo " Try:"
|
|
||||||
echo " a) Unplug USB device from front port"
|
|
||||||
echo " b) Wait 10 seconds"
|
|
||||||
echo " c) Plug back in firmly"
|
|
||||||
echo " d) Wait for it to be recognized (check Control Panel → External Devices)"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "2. **USB Device Format Issue**"
|
|
||||||
echo ""
|
|
||||||
echo " The device was exFAT and got unmounted due to errors."
|
|
||||||
echo ""
|
|
||||||
echo " Try:"
|
|
||||||
echo " a) Format USB device on your Mac to FAT32 or exFAT"
|
|
||||||
echo " b) Reconnect to Synology front port"
|
|
||||||
echo " c) Wait for recognition"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "3. **Unmount and Remount USB Device**"
|
|
||||||
echo ""
|
|
||||||
echo " Via DSM:"
|
|
||||||
echo " a) Control Panel → External Devices"
|
|
||||||
echo " b) If USB device shows, click 'Unmount'"
|
|
||||||
echo " c) Wait 5 seconds"
|
|
||||||
echo " d) Click 'Mount' or reconnect device"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "4. **Check USB Copy Service**"
|
|
||||||
echo ""
|
|
||||||
echo " Via DSM:"
|
|
||||||
echo " a) Package Center → USB Copy"
|
|
||||||
echo " b) Make sure it's 'Started' (not stopped)"
|
|
||||||
echo " c) If stopped, click 'Start'"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "5. **Check USB Copy Task Settings**"
|
|
||||||
echo ""
|
|
||||||
echo " Via DSM:"
|
|
||||||
echo " a) USB Copy → Select your task"
|
|
||||||
echo " b) Task Settings → Verify source is '[USB]'"
|
|
||||||
echo " c) Make sure no other tasks conflict"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "=== Quick Fix Steps ==="
|
|
||||||
echo ""
|
|
||||||
echo "1. Unplug USB device from Synology"
|
|
||||||
echo "2. Wait 10 seconds"
|
|
||||||
echo "3. Plug USB device into FRONT USB port (not rear)"
|
|
||||||
echo "4. Wait 30 seconds for recognition"
|
|
||||||
echo "5. Check Control Panel → External Devices"
|
|
||||||
echo "6. If device appears, try USB Copy again"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "If still not working, check:"
|
|
||||||
echo " - USB device format (FAT32/exFAT recommended)"
|
|
||||||
echo " - USB device not mounted as shared folder"
|
|
||||||
echo " - USB Copy service is running"
|
|
||||||
echo ""
|
|
||||||
@@ -1,131 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Force Delete Stuck Snapshot - Last Resort Methods
|
|
||||||
# When normal deletion methods fail
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Force Delete Stuck Snapshot ==="
|
|
||||||
echo ""
|
|
||||||
echo "This script tries aggressive methods to free stuck snapshot space."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
FREE_SPACE_BEFORE=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB_BEFORE=$(echo "scale=2; $FREE_SPACE_BEFORE / 1024 / 1024" | bc)
|
|
||||||
echo "Current free space: ${FREE_SPACE_GB_BEFORE}GB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
SNAPSHOTS=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$")
|
|
||||||
if [ -z "$SNAPSHOTS" ]; then
|
|
||||||
echo "✅ No snapshots found!"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Found stuck snapshot(s):"
|
|
||||||
echo "$SNAPSHOTS" | sed 's/^/ - /'
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
read -p "Try aggressive cleanup methods? (y/n) " -n 1 -r
|
|
||||||
echo ""
|
|
||||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "Method 1: Aggressive snapshot thinning..."
|
|
||||||
sudo tmutil thinlocalsnapshots / 1000000000 1 2>&1 || true
|
|
||||||
echo " ✓ Completed"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "Method 2: System purge..."
|
|
||||||
if command -v purge &> /dev/null; then
|
|
||||||
sudo purge
|
|
||||||
echo " ✓ Purged"
|
|
||||||
else
|
|
||||||
echo " ⚠️ Purge command not available"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "Method 3: Checking APFS snapshots..."
|
|
||||||
APFS_SNAPS=$(diskutil apfs listSnapshots / 2>/dev/null)
|
|
||||||
if echo "$APFS_SNAPS" | grep -qi "timemachine"; then
|
|
||||||
echo " Found Time Machine snapshot in APFS"
|
|
||||||
# Try to get UUID and delete
|
|
||||||
SNAP_UUID=$(echo "$APFS_SNAPS" | grep -A 2 -i "timemachine" | grep "UUID" | awk '{print $NF}' | head -1)
|
|
||||||
if [ -n "$SNAP_UUID" ]; then
|
|
||||||
echo " Attempting to delete APFS snapshot: $SNAP_UUID"
|
|
||||||
sudo diskutil apfs deleteSnapshot / -uuid "$SNAP_UUID" 2>&1 || echo " ⚠️ Could not delete (may be protected)"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo " ℹ️ Snapshot not in APFS list (ghost entry)"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "Method 4: Force filesystem sync..."
|
|
||||||
sync
|
|
||||||
echo " ✓ Filesystem synced"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "Method 5: Check for Time Machine temp files..."
|
|
||||||
TM_TEMP=$(sudo find /System/Volumes/Data/.timemachine -type f 2>/dev/null | wc -l | tr -d ' ')
|
|
||||||
if [ "$TM_TEMP" -gt 0 ]; then
|
|
||||||
TEMP_SIZE=$(sudo du -sh /System/Volumes/Data/.timemachine 2>/dev/null | awk '{print $1}' || echo "0")
|
|
||||||
echo " Found Time Machine temp files: $TEMP_SIZE"
|
|
||||||
read -p " Delete Time Machine temp files? (y/n) " -n 1 -r
|
|
||||||
echo ""
|
|
||||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
||||||
sudo rm -rf /System/Volumes/Data/.timemachine/* 2>/dev/null || true
|
|
||||||
echo " ✓ Cleaned"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo " ✓ No temp files found"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "⏳ Waiting for system to update..."
|
|
||||||
sleep 5
|
|
||||||
|
|
||||||
# Check results
|
|
||||||
FREE_SPACE_AFTER=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB_AFTER=$(echo "scale=2; $FREE_SPACE_AFTER / 1024 / 1024" | bc)
|
|
||||||
FREED_GB=$(echo "scale=2; $FREE_SPACE_GB_AFTER - $FREE_SPACE_GB_BEFORE" | bc)
|
|
||||||
|
|
||||||
REMAINING_SNAPS=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$" | wc -l | tr -d ' ')
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "=== Results ==="
|
|
||||||
echo " Free space: ${FREE_SPACE_GB_BEFORE}GB → ${FREE_SPACE_GB_AFTER}GB"
|
|
||||||
if (( $(echo "$FREED_GB > 15" | bc -l) )); then
|
|
||||||
echo " ✅ Successfully freed: ${FREED_GB}GB"
|
|
||||||
elif (( $(echo "$FREED_GB > 0" | bc -l) )); then
|
|
||||||
echo " ✅ Freed: ${FREED_GB}GB"
|
|
||||||
else
|
|
||||||
echo " ⚠️ No space freed yet"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$REMAINING_SNAPS" -gt 0 ]; then
|
|
||||||
echo " ⚠️ Snapshot still listed (ghost entry)"
|
|
||||||
echo ""
|
|
||||||
echo " The snapshot entry may persist, but if space was freed,"
|
|
||||||
echo " it's likely just a database entry and not taking space."
|
|
||||||
else
|
|
||||||
echo " ✅ Snapshot removed!"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
if (( $(echo "$FREED_GB < 15" | bc -l) )); then
|
|
||||||
echo "⚠️ Space still not fully freed. Final options:"
|
|
||||||
echo ""
|
|
||||||
echo "1. **Restart your Mac** - This is the most reliable solution."
|
|
||||||
echo " The snapshot will be released after restart."
|
|
||||||
echo ""
|
|
||||||
echo "2. Wait 10-15 minutes - macOS may still be processing"
|
|
||||||
echo ""
|
|
||||||
echo "3. Check if space is actually available but not showing:"
|
|
||||||
echo " - Try creating a large file to test"
|
|
||||||
echo " - Check Activity Monitor → Disk tab"
|
|
||||||
echo ""
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
@@ -1,143 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Force Free Space - Remove APFS and Time Machine Snapshots
|
|
||||||
# This script removes snapshots that are holding onto deleted file space
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Force Free Space - Remove Snapshots ==="
|
|
||||||
echo ""
|
|
||||||
echo "This script will remove APFS and Time Machine snapshots that may be"
|
|
||||||
echo "holding onto space from deleted files."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check current free space
|
|
||||||
FREE_SPACE_BEFORE=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB_BEFORE=$(echo "scale=2; $FREE_SPACE_BEFORE / 1024 / 1024" | bc)
|
|
||||||
echo "Current free space: ${FREE_SPACE_GB_BEFORE}GB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# List current snapshots
|
|
||||||
echo "📸 Current Snapshots:"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "1. Time Machine Local Snapshots:"
|
|
||||||
TM_SNAPSHOTS=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$")
|
|
||||||
if [ -n "$TM_SNAPSHOTS" ]; then
|
|
||||||
echo "$TM_SNAPSHOTS" | while read snapshot; do
|
|
||||||
if [ -n "$snapshot" ]; then
|
|
||||||
echo " - $snapshot"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
else
|
|
||||||
echo " None found"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "2. APFS System Snapshots:"
|
|
||||||
APFS_SNAPSHOTS=$(diskutil apfs listSnapshots / 2>/dev/null | grep -E "Snapshot Name|Snapshot UUID" | head -10)
|
|
||||||
if [ -n "$APFS_SNAPSHOTS" ]; then
|
|
||||||
echo "$APFS_SNAPSHOTS"
|
|
||||||
else
|
|
||||||
echo " None found (or cannot list)"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Ask for confirmation
|
|
||||||
read -p "Do you want to delete Time Machine local snapshots? (y/n) " -n 1 -r
|
|
||||||
echo ""
|
|
||||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
||||||
echo ""
|
|
||||||
echo "🗑️ Deleting Time Machine local snapshots..."
|
|
||||||
|
|
||||||
# Delete each snapshot
|
|
||||||
echo "$TM_SNAPSHOTS" | while read snapshot; do
|
|
||||||
if [ -n "$snapshot" ]; then
|
|
||||||
echo " Deleting: $snapshot"
|
|
||||||
sudo tmutil deletelocalsnapshots "$snapshot" 2>/dev/null && \
|
|
||||||
echo " ✓ Deleted $snapshot" || \
|
|
||||||
echo " ⚠️ Could not delete $snapshot (may be in use)"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# Also try to delete all at once
|
|
||||||
sudo tmutil deletelocalsnapshots / 2>/dev/null || true
|
|
||||||
|
|
||||||
echo " ✓ Time Machine snapshots cleanup attempted"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Force purge of purgeable space
|
|
||||||
echo "3. Purging Purgeable Space..."
|
|
||||||
echo " This forces macOS to actually free up space from deleted files."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
read -p "Do you want to purge purgeable space? (y/n) " -n 1 -r
|
|
||||||
echo ""
|
|
||||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
||||||
echo ""
|
|
||||||
echo " Running purge command..."
|
|
||||||
|
|
||||||
# Method 1: Use purge command (if available)
|
|
||||||
if command -v purge &> /dev/null; then
|
|
||||||
sudo purge
|
|
||||||
echo " ✓ Purge command executed"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Method 2: Disable and re-enable local snapshots to force cleanup
|
|
||||||
echo " Disabling local snapshots..."
|
|
||||||
sudo tmutil disablelocal 2>/dev/null || true
|
|
||||||
sleep 2
|
|
||||||
echo " Re-enabling local snapshots..."
|
|
||||||
sudo tmutil enablelocal 2>/dev/null || true
|
|
||||||
|
|
||||||
# Method 3: Force Time Machine to clean up
|
|
||||||
echo " Triggering Time Machine cleanup..."
|
|
||||||
sudo tmutil thinlocalsnapshots / 1000000000 4 2>/dev/null || true
|
|
||||||
|
|
||||||
echo " ✓ Purge operations completed"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check new free space
|
|
||||||
sleep 2
|
|
||||||
FREE_SPACE_AFTER=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB_AFTER=$(echo "scale=2; $FREE_SPACE_AFTER / 1024 / 1024" | bc)
|
|
||||||
FREED_GB=$(echo "scale=2; $FREE_SPACE_GB_AFTER - $FREE_SPACE_GB_BEFORE" | bc)
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "=== Results ==="
|
|
||||||
echo " Before: ${FREE_SPACE_GB_BEFORE}GB free"
|
|
||||||
echo " After: ${FREE_SPACE_GB_AFTER}GB free"
|
|
||||||
if (( $(echo "$FREED_GB > 0" | bc -l) )); then
|
|
||||||
echo " ✅ Freed: ${FREED_GB}GB"
|
|
||||||
else
|
|
||||||
echo " ⚠️ No space freed yet (may need to wait or try other methods)"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
if (( $(echo "$FREED_GB < 15" | bc -l) )) && (( $(echo "$FREE_SPACE_GB_AFTER < 5" | bc -l) )); then
|
|
||||||
echo "⚠️ Still low on space. Additional steps:"
|
|
||||||
echo ""
|
|
||||||
echo "1. Wait a few minutes - macOS may still be processing"
|
|
||||||
echo ""
|
|
||||||
echo "2. Restart your Mac - this often frees up snapshot space"
|
|
||||||
echo ""
|
|
||||||
echo "3. Check for large files in other locations:"
|
|
||||||
echo " ./free_disk_space.sh"
|
|
||||||
echo ""
|
|
||||||
echo "4. Manually delete the Time Machine snapshot:"
|
|
||||||
SNAP=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$" | head -1)
|
|
||||||
if [ -n "$SNAP" ]; then
|
|
||||||
echo " sudo tmutil deletelocalsnapshots $SNAP"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
echo "5. Use macOS Storage Management:"
|
|
||||||
echo " Apple Menu → About This Mac → Storage → Manage"
|
|
||||||
echo " This tool can identify and remove large system files"
|
|
||||||
echo ""
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Force Purge System Data (351GB)
|
|
||||||
# The 351GB is likely "purgeable" space that macOS won't release until forced
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Force Purge System Data (351GB) ==="
|
|
||||||
echo ""
|
|
||||||
echo "The 351GB in System Data is likely PURGEABLE space."
|
|
||||||
echo "macOS shows it as 'used' but it's actually available."
|
|
||||||
echo "We'll force macOS to release it by creating a large file."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
FREE_SPACE_BEFORE=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB_BEFORE=$(echo "scale=2; $FREE_SPACE_BEFORE / 1024 / 1024" | bc)
|
|
||||||
echo "Current free space: ${FREE_SPACE_GB_BEFORE}GB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🔧 Method: Create a large file to force purge..."
|
|
||||||
echo ""
|
|
||||||
echo " This will:"
|
|
||||||
echo " 1. Create a 50GB file (forces macOS to purge space)"
|
|
||||||
echo " 2. Delete it immediately"
|
|
||||||
echo " 3. This should release the purgeable space"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
read -p "Proceed? This is safe - file will be deleted immediately. (y/n) " -n 1 -r
|
|
||||||
echo ""
|
|
||||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
||||||
echo "Cancelled."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "Creating 50GB test file to force purge..."
|
|
||||||
echo " (This may take a few minutes)"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Create large file to force purge
|
|
||||||
TEST_FILE="$HOME/test_force_purge_$(date +%s).tmp"
|
|
||||||
if dd if=/dev/zero of="$TEST_FILE" bs=1g count=50 2>/dev/null; then
|
|
||||||
echo " ✅ Created 50GB file"
|
|
||||||
echo ""
|
|
||||||
echo " Checking space after creation..."
|
|
||||||
sleep 2
|
|
||||||
FREE_DURING=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_DURING_GB=$(echo "scale=2; $FREE_DURING / 1024 / 1024" | bc)
|
|
||||||
echo " Free space during: ${FREE_DURING_GB}GB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo " Deleting test file..."
|
|
||||||
rm -f "$TEST_FILE"
|
|
||||||
echo " ✅ Deleted"
|
|
||||||
else
|
|
||||||
echo " ⚠️ Could not create file (not enough space or permission issue)"
|
|
||||||
echo " This means the purgeable space may not be available"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "⏳ Waiting for system to update..."
|
|
||||||
sleep 10
|
|
||||||
|
|
||||||
# Check final results
|
|
||||||
FREE_SPACE_AFTER=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB_AFTER=$(echo "scale=2; $FREE_SPACE_AFTER / 1024 / 1024" | bc)
|
|
||||||
FREED_GB=$(echo "scale=2; $FREE_SPACE_GB_AFTER - $FREE_SPACE_GB_BEFORE" | bc)
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "=== Results ==="
|
|
||||||
echo " Before: ${FREE_SPACE_GB_BEFORE}GB free"
|
|
||||||
echo " After: ${FREE_SPACE_GB_AFTER}GB free"
|
|
||||||
if (( $(echo "$FREED_GB > 100" | bc -l) )); then
|
|
||||||
echo " ✅ Successfully freed: ${FREED_GB}GB!"
|
|
||||||
echo " The purgeable space was released!"
|
|
||||||
elif (( $(echo "$FREED_GB > 0" | bc -l) )); then
|
|
||||||
echo " ✅ Freed: ${FREED_GB}GB"
|
|
||||||
else
|
|
||||||
echo " ⚠️ No space freed"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "=== Understanding System Data (351GB) ==="
|
|
||||||
echo ""
|
|
||||||
echo "If System Data still shows 351GB but you have free space,"
|
|
||||||
echo "this is NORMAL macOS behavior:"
|
|
||||||
echo ""
|
|
||||||
echo " - System Data includes PURGEABLE space"
|
|
||||||
echo " - Purgeable space is AVAILABLE but shown as 'used'"
|
|
||||||
echo " - macOS will release it automatically when needed"
|
|
||||||
echo " - The space is actually available for use"
|
|
||||||
echo ""
|
|
||||||
echo "To verify space is available:"
|
|
||||||
echo " 1. Try creating a large file (you just did)"
|
|
||||||
echo " 2. Check Activity Monitor → Disk → Purgeable"
|
|
||||||
echo " 3. The space will be released when you actually need it"
|
|
||||||
echo ""
|
|
||||||
echo "The 351GB in System Data is misleading - much of it"
|
|
||||||
echo "is purgeable and available when needed."
|
|
||||||
echo ""
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Free Disk Space for Time Machine
|
|
||||||
# This script helps identify and free up space on your Mac so Time Machine can work
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Mac Disk Space Analysis ==="
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check current disk usage
|
|
||||||
echo "📊 Current Disk Status:"
|
|
||||||
df -h / | tail -1 | awk '{print " Total: " $2 " | Used: " $3 " (" $5 ") | Free: " $4}'
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check if disk is critically low
|
|
||||||
FREE_SPACE=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB=$(echo "scale=2; $FREE_SPACE / 1024 / 1024" | bc)
|
|
||||||
|
|
||||||
if (( $(echo "$FREE_SPACE_GB < 5" | bc -l) )); then
|
|
||||||
echo "⚠️ WARNING: Disk has less than 5GB free. Time Machine requires free space to work!"
|
|
||||||
echo ""
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "🔍 Analyzing Large Files and Folders:"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check Downloads folder
|
|
||||||
if [ -d ~/Downloads ]; then
|
|
||||||
DOWNLOADS_SIZE=$(du -sh ~/Downloads 2>/dev/null | awk '{print $1}')
|
|
||||||
echo " 📁 Downloads: $DOWNLOADS_SIZE"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check Library Caches
|
|
||||||
if [ -d ~/Library/Caches ]; then
|
|
||||||
CACHES_SIZE=$(du -sh ~/Library/Caches 2>/dev/null | awk '{print $1}')
|
|
||||||
echo " 🗑️ Library/Caches: $CACHES_SIZE (safe to clean)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check Trash
|
|
||||||
if [ -d ~/.Trash ]; then
|
|
||||||
TRASH_SIZE=$(du -sh ~/.Trash 2>/dev/null | awk '{print $1}')
|
|
||||||
echo " 🗑️ Trash: $TRASH_SIZE"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check local Time Machine snapshots
|
|
||||||
echo ""
|
|
||||||
echo "📸 Local Time Machine Snapshots:"
|
|
||||||
SNAPSHOTS=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$" | wc -l | tr -d ' ')
|
|
||||||
if [ "$SNAPSHOTS" -gt 0 ]; then
|
|
||||||
echo " Found $SNAPSHOTS local snapshot(s)"
|
|
||||||
tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$" | sed 's/^/ - /'
|
|
||||||
echo ""
|
|
||||||
echo " 💡 Tip: Local snapshots are automatically deleted when space is needed,"
|
|
||||||
echo " but you can delete them manually if needed."
|
|
||||||
else
|
|
||||||
echo " No local snapshots found"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "📋 Top 10 Largest Files/Directories in Home:"
|
|
||||||
du -h -d 1 ~ 2>/dev/null | sort -hr | head -10 | awk '{printf " %8s %s\n", $1, $2}'
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "=== Recommendations ==="
|
|
||||||
echo ""
|
|
||||||
echo "1. 🗑️ Empty Trash:"
|
|
||||||
echo " rm -rf ~/.Trash/*"
|
|
||||||
echo ""
|
|
||||||
echo "2. 🧹 Clean System Caches (safe):"
|
|
||||||
echo " rm -rf ~/Library/Caches/*"
|
|
||||||
echo ""
|
|
||||||
echo "3. 📁 Review Downloads folder (~/Downloads) - 19GB found"
|
|
||||||
echo " Move large files to NAS or delete if not needed"
|
|
||||||
echo ""
|
|
||||||
echo "4. 🗑️ Delete old local snapshots (if needed):"
|
|
||||||
echo " sudo tmutil deletelocalsnapshots <snapshot-date>"
|
|
||||||
echo ""
|
|
||||||
echo "5. 💾 Use Storage Management:"
|
|
||||||
echo " Apple Menu → About This Mac → Storage → Manage"
|
|
||||||
echo " This tool can help identify and remove large files, old backups, etc."
|
|
||||||
echo ""
|
|
||||||
echo "6. 📦 Check for large applications:"
|
|
||||||
echo " Review Applications folder for unused apps"
|
|
||||||
echo ""
|
|
||||||
echo "=== Quick Clean Commands ==="
|
|
||||||
echo ""
|
|
||||||
echo "To clean caches (safe, will regenerate):"
|
|
||||||
echo " rm -rf ~/Library/Caches/*"
|
|
||||||
echo ""
|
|
||||||
echo "To empty trash:"
|
|
||||||
echo " rm -rf ~/.Trash/*"
|
|
||||||
echo ""
|
|
||||||
echo "To see what's taking up space:"
|
|
||||||
echo " du -h -d 1 ~ | sort -hr | head -20"
|
|
||||||
echo ""
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Free Photo Cache Space
|
|
||||||
# The photo volume is taking 179GB - likely a local cache
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Free Photo Cache Space ==="
|
|
||||||
echo ""
|
|
||||||
echo "Found: /System/Volumes/Data/Volumes/photo is 179GB"
|
|
||||||
echo "This is a mounted NAS share that's being cached locally."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
FREE_SPACE_BEFORE=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB_BEFORE=$(echo "scale=2; $FREE_SPACE_BEFORE / 1024 / 1024" | bc)
|
|
||||||
echo "Current free space: ${FREE_SPACE_GB_BEFORE}GB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check if it's the same as /Volumes/photo
|
|
||||||
echo "🔍 Checking mount points:"
|
|
||||||
MOUNT_POINT=$(mount | grep photo | awk '{print $3}')
|
|
||||||
echo " Network mount: $MOUNT_POINT"
|
|
||||||
echo " Cache location: /System/Volumes/Data/Volumes/photo"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check sizes
|
|
||||||
CACHE_SIZE=$(sudo du -sh /System/Volumes/Data/Volumes/photo 2>/dev/null | awk '{print $1}')
|
|
||||||
MOUNT_SIZE=$(sudo du -sh "$MOUNT_POINT" 2>/dev/null | awk '{print $1}' || echo "N/A")
|
|
||||||
echo " Cache size: $CACHE_SIZE"
|
|
||||||
echo " Mount size: $MOUNT_SIZE"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "⚠️ The 179GB in /System/Volumes/Data/Volumes/photo is likely:"
|
|
||||||
echo " - A local cache of the network share"
|
|
||||||
echo " - Or files that were copied locally"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🔧 Solution:"
|
|
||||||
echo ""
|
|
||||||
echo "Option 1: Unmount the network share (if not needed right now)"
|
|
||||||
echo " diskutil unmount /Volumes/photo"
|
|
||||||
echo " This will free the space immediately"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "Option 2: Clear the cache (if it's a cache)"
|
|
||||||
echo " ⚠️ WARNING: Make sure files are on NAS first!"
|
|
||||||
echo " sudo rm -rf /System/Volumes/Data/Volumes/photo/*"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "Option 3: Check if files are duplicated"
|
|
||||||
echo " Compare /Volumes/photo vs /System/Volumes/Data/Volumes/photo"
|
|
||||||
echo " If they're the same, you can safely remove the cache"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
read -p "Do you want to unmount /Volumes/photo to free space? (y/n) " -n 1 -r
|
|
||||||
echo ""
|
|
||||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
||||||
echo ""
|
|
||||||
echo "Unmounting /Volumes/photo..."
|
|
||||||
if diskutil unmount /Volumes/photo 2>/dev/null; then
|
|
||||||
echo "✅ Successfully unmounted"
|
|
||||||
echo ""
|
|
||||||
echo "⏳ Waiting for space to be released..."
|
|
||||||
sleep 5
|
|
||||||
|
|
||||||
FREE_SPACE_AFTER=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB_AFTER=$(echo "scale=2; $FREE_SPACE_AFTER / 1024 / 1024" | bc)
|
|
||||||
FREED_GB=$(echo "scale=2; $FREE_SPACE_GB_AFTER - $FREE_SPACE_GB_BEFORE" | bc)
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "=== Results ==="
|
|
||||||
echo " Before: ${FREE_SPACE_GB_BEFORE}GB free"
|
|
||||||
echo " After: ${FREE_SPACE_GB_AFTER}GB free"
|
|
||||||
if (( $(echo "$FREED_GB > 150" | bc -l) )); then
|
|
||||||
echo " ✅ Freed: ${FREED_GB}GB (179GB cache released!)"
|
|
||||||
elif (( $(echo "$FREED_GB > 0" | bc -l) )); then
|
|
||||||
echo " ✅ Freed: ${FREED_GB}GB"
|
|
||||||
else
|
|
||||||
echo " ⚠️ Space not freed yet (may need to clear cache manually)"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "⚠️ Could not unmount (may be in use)"
|
|
||||||
echo " Try: sudo umount /Volumes/photo"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
@@ -1,156 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Free Space Without Triggering Snapshot Growth
|
|
||||||
# Delete files that are ALREADY in snapshots or don't trigger snapshots
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Free Space Without Snapshot Growth ==="
|
|
||||||
echo ""
|
|
||||||
echo "⚠️ CRITICAL: Stop deleting regular files!"
|
|
||||||
echo " Every file you delete is preserved in the OS snapshot,"
|
|
||||||
echo " making System Data grow."
|
|
||||||
echo ""
|
|
||||||
echo "Instead, delete files that DON'T trigger snapshot growth:"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
FREE_SPACE_BEFORE=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB_BEFORE=$(echo "scale=2; $FREE_SPACE_BEFORE / 1024 / 1024" | bc)
|
|
||||||
echo "Current free space: ${FREE_SPACE_GB_BEFORE}GB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🔧 Safe to Delete (Won't Grow System Data):"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 1. Caches (already cached, deleting doesn't create new snapshots)
|
|
||||||
echo "1. Library Caches (~6GB):"
|
|
||||||
CACHE_SIZE=$(du -sh ~/Library/Caches 2>/dev/null | awk '{print $1}' || echo "0")
|
|
||||||
echo " Size: $CACHE_SIZE"
|
|
||||||
echo " Command: rm -rf ~/Library/Caches/*"
|
|
||||||
echo " ✅ Safe - caches are temporary"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 2. User cache
|
|
||||||
echo "2. User Cache (~3GB):"
|
|
||||||
USER_CACHE=$(du -sh ~/.cache 2>/dev/null | awk '{print $1}' || echo "0")
|
|
||||||
echo " Size: $USER_CACHE"
|
|
||||||
echo " Command: rm -rf ~/.cache/*"
|
|
||||||
echo " ✅ Safe - temporary files"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 3. Downloads (if already backed up)
|
|
||||||
echo "3. Downloads (~9GB):"
|
|
||||||
DOWNLOADS_SIZE=$(du -sh ~/Downloads 2>/dev/null | awk '{print $1}' || echo "0")
|
|
||||||
echo " Size: $DOWNLOADS_SIZE"
|
|
||||||
echo " ⚠️ Only if files are already on NAS"
|
|
||||||
echo " Command: rm -rf ~/Downloads/*"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 4. Trash
|
|
||||||
echo "4. Trash:"
|
|
||||||
TRASH_SIZE=$(du -sh ~/.Trash 2>/dev/null | awk '{print $1}' || echo "0")
|
|
||||||
echo " Size: $TRASH_SIZE"
|
|
||||||
echo " Command: rm -rf ~/.Trash/*"
|
|
||||||
echo " ✅ Safe - already deleted"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 5. npm cache
|
|
||||||
echo "5. npm Cache (~1GB):"
|
|
||||||
NPM_SIZE=$(du -sh ~/.npm 2>/dev/null | awk '{print $1}' || echo "0")
|
|
||||||
echo " Size: $NPM_SIZE"
|
|
||||||
echo " Command: npm cache clean --force"
|
|
||||||
echo " ✅ Safe - can be regenerated"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
TOTAL_SAFE=$(echo "6 + 3 + 1" | bc)
|
|
||||||
echo "Estimated safe space to free: ~${TOTAL_SAFE}GB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
read -p "Clean these safe items now? (y/n) " -n 1 -r
|
|
||||||
echo ""
|
|
||||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
||||||
echo ""
|
|
||||||
echo "🧹 Cleaning safe items..."
|
|
||||||
|
|
||||||
# Clean caches
|
|
||||||
if [ -d ~/Library/Caches ]; then
|
|
||||||
rm -rf ~/Library/Caches/* 2>/dev/null || true
|
|
||||||
echo " ✅ Cleaned Library/Caches"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -d ~/.cache ]; then
|
|
||||||
rm -rf ~/.cache/* 2>/dev/null || true
|
|
||||||
echo " ✅ Cleaned user cache"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Clean trash
|
|
||||||
if [ -d ~/.Trash ]; then
|
|
||||||
rm -rf ~/.Trash/* 2>/dev/null || true
|
|
||||||
echo " ✅ Emptied Trash"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Clean npm
|
|
||||||
if command -v npm &> /dev/null && [ -d ~/.npm ]; then
|
|
||||||
npm cache clean --force 2>/dev/null || true
|
|
||||||
echo " ✅ Cleaned npm cache"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "⏳ Waiting for system to update..."
|
|
||||||
sleep 5
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check results
|
|
||||||
FREE_SPACE_AFTER=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB_AFTER=$(echo "scale=2; $FREE_SPACE_AFTER / 1024 / 1024" | bc)
|
|
||||||
FREED_GB=$(echo "scale=2; $FREE_SPACE_GB_AFTER - $FREE_SPACE_GB_BEFORE" | bc)
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "=== Results ==="
|
|
||||||
echo " Before: ${FREE_SPACE_GB_BEFORE}GB free"
|
|
||||||
echo " After: ${FREE_SPACE_GB_AFTER}GB free"
|
|
||||||
if (( $(echo "$FREED_GB > 0" | bc -l) )); then
|
|
||||||
echo " ✅ Freed: ${FREED_GB}GB"
|
|
||||||
else
|
|
||||||
echo " ⚠️ No space freed (may need restart)"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "=== CRITICAL INSTRUCTIONS ==="
|
|
||||||
echo ""
|
|
||||||
echo "1. ⛔ STOP DELETING REGULAR FILES"
|
|
||||||
echo " Every file you delete makes System Data grow!"
|
|
||||||
echo ""
|
|
||||||
echo "2. ✅ Only delete:"
|
|
||||||
echo " - Caches (already done above)"
|
|
||||||
echo " - Trash (already done above)"
|
|
||||||
echo " - Files that are already on NAS"
|
|
||||||
echo ""
|
|
||||||
echo "3. 🚀 Install macOS Update NOW:"
|
|
||||||
echo " System Settings → General → Software Update"
|
|
||||||
echo " Install macOS Tahoe 26.2"
|
|
||||||
echo ""
|
|
||||||
echo " The update will:"
|
|
||||||
echo " - Clear the old snapshot"
|
|
||||||
echo " - Free the 351GB in System Data"
|
|
||||||
echo " - Stop the snapshot growth problem"
|
|
||||||
echo ""
|
|
||||||
echo "4. ⏳ If you don't have enough space for update:"
|
|
||||||
echo " - The update needs ~3.6GB"
|
|
||||||
echo " - Try downloading it first (may work with less space)"
|
|
||||||
echo " - Or move files to NAS instead of deleting"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
if (( $(echo "$FREE_SPACE_GB_AFTER < 4" | bc -l) )); then
|
|
||||||
echo "⚠️ Still low on space for update."
|
|
||||||
echo ""
|
|
||||||
echo " Try downloading the update first:"
|
|
||||||
echo " sudo softwareupdate --download --all"
|
|
||||||
echo ""
|
|
||||||
echo " Or move (don't delete) large files to NAS:"
|
|
||||||
echo " - Documents folder (40GB)"
|
|
||||||
echo " - .ollama models (17GB)"
|
|
||||||
echo ""
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
@@ -1,111 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Free System Data (351GB)
|
|
||||||
# Most of this is purgeable space held by snapshots
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Free System Data (351GB) ==="
|
|
||||||
echo ""
|
|
||||||
echo "System Data is 351GB, but visible components only add up to ~20GB."
|
|
||||||
echo "This means ~330GB is PURGEABLE SPACE held by snapshots."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
FREE_SPACE_BEFORE=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB_BEFORE=$(echo "scale=2; $FREE_SPACE_BEFORE / 1024 / 1024" | bc)
|
|
||||||
echo "Current free space: ${FREE_SPACE_GB_BEFORE}GB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🔧 Step 1: Aggressively thin all snapshots..."
|
|
||||||
sudo tmutil thinlocalsnapshots / 1000000000 1 2>&1
|
|
||||||
echo " ✓ Completed"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🔧 Step 2: Purge system memory and caches..."
|
|
||||||
if command -v purge &> /dev/null; then
|
|
||||||
sudo purge
|
|
||||||
echo " ✓ Purged"
|
|
||||||
else
|
|
||||||
echo " ⚠️ Purge command not available"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🔧 Step 3: Remove Time Machine destination (CRITICAL)"
|
|
||||||
echo ""
|
|
||||||
echo " ⚠️ IMPORTANT: You MUST remove Time Machine destination to"
|
|
||||||
echo " prevent new snapshots from being created!"
|
|
||||||
echo ""
|
|
||||||
echo " Do this now:"
|
|
||||||
echo " 1. System Settings → General → Time Machine"
|
|
||||||
echo " 2. Click '-' to remove backup disk"
|
|
||||||
echo " 3. Confirm removal"
|
|
||||||
echo ""
|
|
||||||
read -p " Have you removed Time Machine destination? (y/n) " -n 1 -r
|
|
||||||
echo ""
|
|
||||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
||||||
echo " ⚠️ Please remove it first, then run this script again."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "🔧 Step 4: Wait for system to release purgeable space..."
|
|
||||||
echo " This may take a few minutes..."
|
|
||||||
sleep 10
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "🔧 Step 5: Try to delete stuck snapshot..."
|
|
||||||
SNAPSHOT=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$" | head -1)
|
|
||||||
if [ -n "$SNAPSHOT" ]; then
|
|
||||||
SNAP_DATE=$(echo "$SNAPSHOT" | sed 's/.*\.\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}\)\.backup/\1/')
|
|
||||||
echo " Attempting to delete: $SNAPSHOT"
|
|
||||||
if sudo tmutil deletelocalsnapshots "$SNAP_DATE" 2>/dev/null; then
|
|
||||||
echo " ✅ Deleted!"
|
|
||||||
else
|
|
||||||
echo " ⚠️ Still stuck (ghost entry - will clear on restart)"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo " ✅ No snapshots found"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "⏳ Waiting for space to be released..."
|
|
||||||
sleep 10
|
|
||||||
|
|
||||||
# Check results
|
|
||||||
FREE_SPACE_AFTER=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB_AFTER=$(echo "scale=2; $FREE_SPACE_AFTER / 1024 / 1024" | bc)
|
|
||||||
FREED_GB=$(echo "scale=2; $FREE_SPACE_GB_AFTER - $FREE_SPACE_GB_BEFORE" | bc)
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "=== Results ==="
|
|
||||||
echo " Before: ${FREE_SPACE_GB_BEFORE}GB free"
|
|
||||||
echo " After: ${FREE_SPACE_GB_AFTER}GB free"
|
|
||||||
if (( $(echo "$FREED_GB > 100" | bc -l) )); then
|
|
||||||
echo " ✅ Successfully freed: ${FREED_GB}GB!"
|
|
||||||
elif (( $(echo "$FREED_GB > 0" | bc -l) )); then
|
|
||||||
echo " ✅ Freed: ${FREED_GB}GB"
|
|
||||||
echo " (More space may be released over time)"
|
|
||||||
else
|
|
||||||
echo " ⚠️ No space freed yet"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
if (( $(echo "$FREE_SPACE_GB_AFTER < 50" | bc -l) )); then
|
|
||||||
echo "⚠️ Still low on space. Additional steps:"
|
|
||||||
echo ""
|
|
||||||
echo "1. **Restart your Mac** - This is the most effective way"
|
|
||||||
echo " to release purgeable space from snapshots."
|
|
||||||
echo ""
|
|
||||||
echo "2. Use macOS Storage Management:"
|
|
||||||
echo " Apple Menu → About This Mac → Storage → Manage"
|
|
||||||
echo " Click 'Optimize' to release purgeable space"
|
|
||||||
echo ""
|
|
||||||
echo "3. Wait 15-30 minutes - macOS may need time to"
|
|
||||||
echo " release the purgeable space"
|
|
||||||
echo ""
|
|
||||||
echo "4. The 351GB in System Data is mostly purgeable space"
|
|
||||||
echo " that will be released when snapshots are cleared."
|
|
||||||
echo ""
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Script to get detailed EnConvo crash information
|
|
||||||
|
|
||||||
echo "=== EnConvo Crash Details Collector ==="
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 1. Check for crash reports
|
|
||||||
echo "1. Recent Crash Reports:"
|
|
||||||
CRASH_REPORTS=$(ls -t ~/Library/Logs/DiagnosticReports/*EnConvo* 2>/dev/null | head -3)
|
|
||||||
if [ -z "$CRASH_REPORTS" ]; then
|
|
||||||
echo " No crash reports found in DiagnosticReports"
|
|
||||||
else
|
|
||||||
echo " Found crash reports:"
|
|
||||||
echo "$CRASH_REPORTS" | while read report; do
|
|
||||||
echo " - $(basename "$report")"
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 2. Get the most recent crash report summary
|
|
||||||
echo "2. Most Recent Crash Report Summary:"
|
|
||||||
LATEST_CRASH=$(ls -t ~/Library/Logs/DiagnosticReports/*EnConvo* 2>/dev/null | head -1)
|
|
||||||
if [ -n "$LATEST_CRASH" ]; then
|
|
||||||
echo " File: $(basename "$LATEST_CRASH")"
|
|
||||||
echo ""
|
|
||||||
echo " Exception Type:"
|
|
||||||
grep -A 5 "Exception Type:" "$LATEST_CRASH" 2>/dev/null | head -6 || echo " (Not found)"
|
|
||||||
echo ""
|
|
||||||
echo " Crashed Thread:"
|
|
||||||
grep -A 10 "Crashed Thread:" "$LATEST_CRASH" 2>/dev/null | head -11 || echo " (Not found)"
|
|
||||||
echo ""
|
|
||||||
echo " Application Specific Information:"
|
|
||||||
grep -A 5 "Application Specific Information:" "$LATEST_CRASH" 2>/dev/null | head -6 || echo " (Not found)"
|
|
||||||
else
|
|
||||||
echo " No crash report found. The app may have exited without creating one."
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 3. Check Console logs
|
|
||||||
echo "3. Recent Console Logs (last 30 seconds):"
|
|
||||||
log show --predicate 'process == "EnConvo" AND eventMessage CONTAINS "error" OR eventMessage CONTAINS "crash" OR eventMessage CONTAINS "exception"' --last 30s --style compact 2>/dev/null | tail -10 || echo " (No relevant logs found)"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "=== To view full crash report, run: ==="
|
|
||||||
if [ -n "$LATEST_CRASH" ]; then
|
|
||||||
echo "open '$LATEST_CRASH'"
|
|
||||||
else
|
|
||||||
echo "# No crash report found yet"
|
|
||||||
echo "# After the crash, run: ls -t ~/Library/Logs/DiagnosticReports/*EnConvo* | head -1 | xargs open"
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Install Tailscale on server2
|
|
||||||
# This script will detect the OS and install Tailscale accordingly
|
|
||||||
|
|
||||||
echo "=== Installing Tailscale on server2 ==="
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Detect OS and install Tailscale
|
|
||||||
echo "Detecting OS and installing Tailscale..."
|
|
||||||
ssh server2 << 'EOF'
|
|
||||||
# Detect OS
|
|
||||||
if [ -f /etc/os-release ]; then
|
|
||||||
. /etc/os-release
|
|
||||||
OS=$ID
|
|
||||||
VER=$VERSION_ID
|
|
||||||
else
|
|
||||||
echo "Cannot detect OS. Assuming Ubuntu/Debian."
|
|
||||||
OS="ubuntu"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Detected OS: $OS $VER"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Install Tailscale based on OS
|
|
||||||
case $OS in
|
|
||||||
ubuntu|debian)
|
|
||||||
echo "Installing Tailscale on Ubuntu/Debian..."
|
|
||||||
curl -fsSL https://tailscale.com/install.sh | sh
|
|
||||||
;;
|
|
||||||
fedora|rhel|centos|rocky|almalinux)
|
|
||||||
echo "Installing Tailscale on RHEL/CentOS/Fedora..."
|
|
||||||
curl -fsSL https://tailscale.com/install.sh | sh
|
|
||||||
;;
|
|
||||||
arch|manjaro)
|
|
||||||
echo "Installing Tailscale on Arch Linux..."
|
|
||||||
curl -fsSL https://tailscale.com/install.sh | sh
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Using generic Linux installation..."
|
|
||||||
curl -fsSL https://tailscale.com/install.sh | sh
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "Tailscale installation complete!"
|
|
||||||
echo ""
|
|
||||||
echo "Next steps:"
|
|
||||||
echo "1. Run: sudo tailscale up"
|
|
||||||
echo "2. Follow the authentication link to connect this machine to your Tailscale network"
|
|
||||||
echo ""
|
|
||||||
echo "To check status: sudo tailscale status"
|
|
||||||
EOF
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "=== Installation script completed ==="
|
|
||||||
echo ""
|
|
||||||
echo "To authenticate and start Tailscale, run:"
|
|
||||||
echo " ssh server2 'sudo tailscale up'"
|
|
||||||
echo ""
|
|
||||||
echo "This will provide a URL to authenticate the device."
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,259 +0,0 @@
|
|||||||
# iPhone Mirroring Troubleshooting
|
|
||||||
|
|
||||||
## Issue
|
|
||||||
iPhone Mirroring shows "Unable to Connect to iPhone" error, even though:
|
|
||||||
- ✅ Same iPhone works on another MacBook
|
|
||||||
- ✅ iPhone is near the Mac, powered on
|
|
||||||
- ✅ iPhone is running iOS 18 or later
|
|
||||||
|
|
||||||
## Requirements Checklist
|
|
||||||
|
|
||||||
### iPhone Requirements
|
|
||||||
- [ ] iOS 18.0 or later
|
|
||||||
- [ ] Bluetooth enabled
|
|
||||||
- [ ] Wi-Fi enabled
|
|
||||||
- [ ] Signed in to iCloud with same Apple ID as Mac
|
|
||||||
- [ ] iPhone is unlocked (or recently unlocked)
|
|
||||||
- [ ] iPhone is near the Mac (within Bluetooth range)
|
|
||||||
|
|
||||||
### Mac Requirements
|
|
||||||
- [ ] macOS Sequoia 15.0 or later
|
|
||||||
- [ ] Bluetooth enabled
|
|
||||||
- [ ] Wi-Fi enabled
|
|
||||||
- [ ] Signed in to iCloud with same Apple ID as iPhone
|
|
||||||
- [ ] Continuity features enabled
|
|
||||||
|
|
||||||
## Common Causes & Solutions
|
|
||||||
|
|
||||||
### 1. Different iCloud Account
|
|
||||||
**Most Common Issue**: Mac and iPhone signed in to different iCloud accounts
|
|
||||||
|
|
||||||
**Check:**
|
|
||||||
```bash
|
|
||||||
# On Mac - check iCloud account
|
|
||||||
defaults read MobileMeAccounts Accounts | grep AccountID
|
|
||||||
|
|
||||||
# Or check System Settings → Apple ID
|
|
||||||
```
|
|
||||||
|
|
||||||
**Fix:**
|
|
||||||
- System Settings → Apple ID → Sign in with same account as iPhone
|
|
||||||
- iPhone: Settings → [Your Name] → Verify Apple ID matches
|
|
||||||
|
|
||||||
### 2. Continuity Features Disabled
|
|
||||||
**Check:**
|
|
||||||
- System Settings → General → AirDrop & Handoff
|
|
||||||
- Ensure "Handoff" is enabled
|
|
||||||
- Ensure "Allow Handoff between this Mac and your iCloud devices" is checked
|
|
||||||
|
|
||||||
**Fix:**
|
|
||||||
```bash
|
|
||||||
# Enable Handoff via command line
|
|
||||||
defaults write com.apple.coreservices.useractivityd.plist ActivityAdvertisingAllowed -bool true
|
|
||||||
defaults write com.apple.coreservices.useractivityd.plist ActivityReceivingAllowed -bool true
|
|
||||||
|
|
||||||
# Restart the service
|
|
||||||
killall sharingd
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Bluetooth/Wi-Fi Issues
|
|
||||||
**Check:**
|
|
||||||
```bash
|
|
||||||
# Check Bluetooth status
|
|
||||||
system_profiler SPBluetoothDataType | grep -A 5 "State"
|
|
||||||
|
|
||||||
# Check Wi-Fi status
|
|
||||||
networksetup -getairportpower en0
|
|
||||||
```
|
|
||||||
|
|
||||||
**Fix:**
|
|
||||||
- Turn Bluetooth off and on: System Settings → Bluetooth
|
|
||||||
- Turn Wi-Fi off and on: System Settings → Wi-Fi
|
|
||||||
- Restart both devices
|
|
||||||
|
|
||||||
### 4. macOS Version Too Old
|
|
||||||
**Check:**
|
|
||||||
```bash
|
|
||||||
sw_vers
|
|
||||||
```
|
|
||||||
|
|
||||||
**Fix:**
|
|
||||||
- iPhone Mirroring requires macOS Sequoia 15.0 or later
|
|
||||||
- Update macOS: System Settings → General → Software Update
|
|
||||||
|
|
||||||
### 5. Firewall Blocking Connection
|
|
||||||
**Check:**
|
|
||||||
- System Settings → Network → Firewall
|
|
||||||
- Check if Firewall is enabled
|
|
||||||
|
|
||||||
**Fix:**
|
|
||||||
- Temporarily disable Firewall to test
|
|
||||||
- If it works, add exception for "Continuity" or "Handoff"
|
|
||||||
- Or ensure "Block all incoming connections" is NOT checked
|
|
||||||
|
|
||||||
### 6. Network Isolation
|
|
||||||
**Check:**
|
|
||||||
- Are Mac and iPhone on the same Wi-Fi network?
|
|
||||||
- Is there a VPN active on either device?
|
|
||||||
|
|
||||||
**Fix:**
|
|
||||||
- Connect both to same Wi-Fi network
|
|
||||||
- Disable VPN temporarily to test
|
|
||||||
- Ensure network allows device-to-device communication (not in guest/isolated mode)
|
|
||||||
|
|
||||||
### 7. Bluetooth Permissions
|
|
||||||
**Check:**
|
|
||||||
- System Settings → Privacy & Security → Bluetooth
|
|
||||||
- Ensure apps have Bluetooth access
|
|
||||||
|
|
||||||
**Fix:**
|
|
||||||
- Grant Bluetooth permissions if prompted
|
|
||||||
- Restart Mac after granting permissions
|
|
||||||
|
|
||||||
### 8. Stale Continuity Cache
|
|
||||||
**Fix:**
|
|
||||||
```bash
|
|
||||||
# Reset Continuity/Handoff cache
|
|
||||||
killall sharingd
|
|
||||||
killall bluetoothd
|
|
||||||
|
|
||||||
# Or restart Bluetooth daemon
|
|
||||||
sudo launchctl stop com.apple.bluetoothd
|
|
||||||
sudo launchctl start com.apple.bluetoothd
|
|
||||||
```
|
|
||||||
|
|
||||||
### 9. Reset Network Settings (Last Resort)
|
|
||||||
**On iPhone:**
|
|
||||||
- Settings → General → Transfer or Reset iPhone → Reset → Reset Network Settings
|
|
||||||
- This will reset Wi-Fi passwords but may fix connection issues
|
|
||||||
|
|
||||||
**On Mac:**
|
|
||||||
```bash
|
|
||||||
# Reset network location (less drastic)
|
|
||||||
sudo networksetup -setairportpower en0 off
|
|
||||||
sleep 2
|
|
||||||
sudo networksetup -setairportpower en0 on
|
|
||||||
```
|
|
||||||
|
|
||||||
## Diagnostic Commands
|
|
||||||
|
|
||||||
### Check Continuity Status
|
|
||||||
```bash
|
|
||||||
# Check Handoff status
|
|
||||||
defaults read com.apple.coreservices.useractivityd.plist
|
|
||||||
|
|
||||||
# Check Bluetooth connectivity
|
|
||||||
system_profiler SPBluetoothDataType | grep -i "connected\|paired"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Check System Logs
|
|
||||||
```bash
|
|
||||||
# Check for iPhone Mirroring errors
|
|
||||||
log show --predicate 'eventMessage contains "iPhone Mirroring" or eventMessage contains "Continuity"' --last 1h --info
|
|
||||||
|
|
||||||
# Check Bluetooth errors
|
|
||||||
log show --predicate 'subsystem == "com.apple.bluetooth"' --last 1h --info | tail -50
|
|
||||||
```
|
|
||||||
|
|
||||||
### Check iCloud Account Match
|
|
||||||
```bash
|
|
||||||
# Mac iCloud account
|
|
||||||
defaults read MobileMeAccounts Accounts | grep -A 5 "AccountID"
|
|
||||||
|
|
||||||
# Compare with iPhone (check iPhone Settings → [Your Name])
|
|
||||||
```
|
|
||||||
|
|
||||||
### Test Bluetooth Connection
|
|
||||||
```bash
|
|
||||||
# List nearby Bluetooth devices
|
|
||||||
system_profiler SPBluetoothDataType | grep -A 10 "iPhone"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Step-by-Step Troubleshooting
|
|
||||||
|
|
||||||
1. **Verify Requirements:**
|
|
||||||
- Check macOS version (must be 15.0+)
|
|
||||||
- Check iOS version (must be 18.0+)
|
|
||||||
- Verify same iCloud account on both devices
|
|
||||||
|
|
||||||
2. **Restart Services:**
|
|
||||||
```bash
|
|
||||||
killall sharingd
|
|
||||||
killall bluetoothd
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Restart Both Devices:**
|
|
||||||
- Restart Mac
|
|
||||||
- Restart iPhone
|
|
||||||
|
|
||||||
4. **Check System Settings:**
|
|
||||||
- System Settings → General → AirDrop & Handoff → Enable Handoff
|
|
||||||
- System Settings → Privacy & Security → Bluetooth → Ensure enabled
|
|
||||||
- System Settings → Network → Firewall → Check settings
|
|
||||||
|
|
||||||
5. **Try Again:**
|
|
||||||
- Make sure iPhone is unlocked
|
|
||||||
- Bring iPhone close to Mac
|
|
||||||
- Try connecting again
|
|
||||||
|
|
||||||
6. **If Still Not Working:**
|
|
||||||
- Sign out and sign back into iCloud on Mac
|
|
||||||
- Sign out and sign back into iCloud on iPhone
|
|
||||||
- Try again
|
|
||||||
|
|
||||||
## Comparison with Working MacBook
|
|
||||||
|
|
||||||
Since it works on another MacBook, compare:
|
|
||||||
|
|
||||||
1. **macOS Version:**
|
|
||||||
```bash
|
|
||||||
sw_vers # On both Macs
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **iCloud Account:**
|
|
||||||
- Verify both Macs use same iCloud account
|
|
||||||
- Check System Settings → Apple ID
|
|
||||||
|
|
||||||
3. **System Settings:**
|
|
||||||
- Compare AirDrop & Handoff settings
|
|
||||||
- Compare Firewall settings
|
|
||||||
- Compare Bluetooth/Wi-Fi settings
|
|
||||||
|
|
||||||
4. **Network:**
|
|
||||||
- Are both Macs on same network?
|
|
||||||
- Any VPN differences?
|
|
||||||
|
|
||||||
## Quick Fix Script
|
|
||||||
|
|
||||||
```bash
|
|
||||||
#!/bin/bash
|
|
||||||
# Quick fix for iPhone Mirroring issues
|
|
||||||
|
|
||||||
echo "Resetting Continuity services..."
|
|
||||||
killall sharingd 2>/dev/null
|
|
||||||
killall bluetoothd 2>/dev/null
|
|
||||||
|
|
||||||
echo "Restarting Bluetooth..."
|
|
||||||
sudo launchctl stop com.apple.bluetoothd 2>/dev/null
|
|
||||||
sudo launchctl start com.apple.bluetoothd 2>/dev/null
|
|
||||||
|
|
||||||
echo "Checking Handoff settings..."
|
|
||||||
defaults read com.apple.coreservices.useractivityd.plist ActivityAdvertisingAllowed
|
|
||||||
defaults read com.apple.coreservices.useractivityd.plist ActivityReceivingAllowed
|
|
||||||
|
|
||||||
echo "Done. Please restart your Mac and try again."
|
|
||||||
```
|
|
||||||
|
|
||||||
## Notes
|
|
||||||
|
|
||||||
- iPhone Mirroring requires **macOS Sequoia 15.0+** and **iOS 18.0+**
|
|
||||||
- Both devices must be on same Wi-Fi network (or have Wi-Fi enabled even if using cellular)
|
|
||||||
- Bluetooth must be enabled on both devices (used for proximity detection)
|
|
||||||
- Same iCloud account is **required** (not just signed in, but same account)
|
|
||||||
- Some corporate networks block device-to-device communication
|
|
||||||
- VPNs can interfere with Continuity features
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
# iPhone Proxy Setup Guide
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
- ✅ Tailscale installed and connected on iPhone
|
|
||||||
- ✅ server2 proxy running at `100.70.115.1`
|
|
||||||
|
|
||||||
## Option 1: System-Wide Proxy (Limited Support)
|
|
||||||
|
|
||||||
iOS has limited system-wide proxy support. This works for some apps but not all browsers.
|
|
||||||
|
|
||||||
### Steps:
|
|
||||||
1. Open **Settings** → **Wi-Fi**
|
|
||||||
2. Tap the **ⓘ** icon next to your connected Wi-Fi network
|
|
||||||
3. Scroll down to **HTTP Proxy**
|
|
||||||
4. Select **Manual**
|
|
||||||
5. Configure:
|
|
||||||
- **Server:** `100.70.115.1`
|
|
||||||
- **Port:** `7890` (HTTP) or `7892` (Mixed)
|
|
||||||
- **Authentication:** Off
|
|
||||||
6. Save
|
|
||||||
|
|
||||||
**Note:** This only works when connected to that specific Wi-Fi network. It won't work on cellular or other Wi-Fi networks.
|
|
||||||
|
|
||||||
## Option 2: Proxy App (Recommended)
|
|
||||||
|
|
||||||
**⚠️ Important: VPN Conflict Solution**
|
|
||||||
|
|
||||||
iOS only allows **one VPN connection** at a time. Since Tailscale uses VPN mode, you have two options:
|
|
||||||
|
|
||||||
### Solution A: Use Shadowrocket in Proxy Mode (Recommended)
|
|
||||||
|
|
||||||
Shadowrocket can work **WITH Tailscale** if configured correctly:
|
|
||||||
|
|
||||||
1. **Keep Tailscale ON** (for network access)
|
|
||||||
2. Install **Shadowrocket** from App Store
|
|
||||||
3. Open Shadowrocket
|
|
||||||
4. Tap **+** (Add Server)
|
|
||||||
5. Select **HTTP** (not VPN mode)
|
|
||||||
6. Configure:
|
|
||||||
- **Type:** HTTP
|
|
||||||
- **Address:** `100.70.115.1` (Tailscale IP)
|
|
||||||
- **Port:** `7890`
|
|
||||||
- **Name:** server2-proxy
|
|
||||||
7. Tap **Done**
|
|
||||||
8. **Important:** In Shadowrocket settings:
|
|
||||||
- Go to **Settings** → **Proxy**
|
|
||||||
- Enable **"Use Proxy"** but **DO NOT enable VPN mode**
|
|
||||||
- Or use **"Proxy" mode** instead of **"VPN" mode**
|
|
||||||
9. Enable the proxy
|
|
||||||
|
|
||||||
**How it works:** Shadowrocket routes traffic through the proxy, but uses Tailscale's VPN connection to reach the proxy server. Both work together!
|
|
||||||
|
|
||||||
### Solution B: Use Shadowrocket VPN Mode (Disable Tailscale)
|
|
||||||
|
|
||||||
If you need Shadowrocket's VPN mode:
|
|
||||||
1. **Disable Tailscale** temporarily
|
|
||||||
2. Use Shadowrocket in VPN mode
|
|
||||||
3. Shadowrocket will handle both VPN and proxy routing
|
|
||||||
|
|
||||||
**Note:** You'll lose direct Tailscale network access, but can still reach server2 via proxy.
|
|
||||||
|
|
||||||
### Surge (Paid, ~$10)
|
|
||||||
Similar setup process - supports more advanced features.
|
|
||||||
|
|
||||||
### Potatso Lite (Free)
|
|
||||||
1. Install **Potatso Lite**
|
|
||||||
2. Add proxy with same settings
|
|
||||||
|
|
||||||
## Option 3: Safari Browser Extension
|
|
||||||
|
|
||||||
Some browsers support proxy extensions, but iOS Safari doesn't support system proxies well.
|
|
||||||
|
|
||||||
## Option 4: Clash Client for iOS
|
|
||||||
|
|
||||||
If you want to use Clash directly on iPhone:
|
|
||||||
|
|
||||||
### Clash Meta for iOS (Stash)
|
|
||||||
1. Install **Stash** from App Store (or use TestFlight)
|
|
||||||
2. Add your server2 as an HTTP proxy
|
|
||||||
3. Configure routing rules
|
|
||||||
|
|
||||||
## Quick Test
|
|
||||||
|
|
||||||
After setup, test if proxy is working:
|
|
||||||
|
|
||||||
1. Open Safari or your browser
|
|
||||||
2. Visit: https://api.ipify.org
|
|
||||||
3. It should show server2's IP: `158.101.140.85` (not your iPhone's IP)
|
|
||||||
|
|
||||||
Or visit: http://100.70.115.1:9090/ui to see Clash dashboard
|
|
||||||
|
|
||||||
## Recommended Setup
|
|
||||||
|
|
||||||
**Best Solution: Use Both Together**
|
|
||||||
- **Keep Tailscale ON** (for network connectivity)
|
|
||||||
- Use **Shadowrocket in Proxy mode** (not VPN mode)
|
|
||||||
- Configure HTTP proxy: `100.70.115.1:7890`
|
|
||||||
- Shadowrocket will route through Tailscale's connection
|
|
||||||
- Works on both Wi-Fi and cellular
|
|
||||||
|
|
||||||
**Alternative: Use Shadowrocket VPN Mode**
|
|
||||||
- Disable Tailscale when using Shadowrocket VPN mode
|
|
||||||
- Shadowrocket handles both VPN and proxy
|
|
||||||
- You'll need to manually switch between them
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### VPN Conflict?
|
|
||||||
- **If both Tailscale and Shadowrocket show VPN icons:** You can only have one active
|
|
||||||
- **Solution:** Use Shadowrocket in **Proxy mode** (not VPN mode) while Tailscale is active
|
|
||||||
- **Or:** Disable Tailscale and use Shadowrocket VPN mode
|
|
||||||
|
|
||||||
### Can't connect?
|
|
||||||
1. Verify Tailscale is connected on iPhone (needed to reach `100.70.115.1`)
|
|
||||||
2. Check Tailscale status: Open Tailscale app, verify you see "oracle-tokyo" device
|
|
||||||
3. Test connection: Open Safari, visit `http://100.70.115.1:9090/ui`
|
|
||||||
4. If dashboard loads, proxy is reachable via Tailscale
|
|
||||||
|
|
||||||
### Proxy not working?
|
|
||||||
1. Check if proxy app is enabled/running
|
|
||||||
2. Verify server2 is online: `ssh server2 'sudo systemctl status clash-meta'`
|
|
||||||
3. Try different port: 7890 (HTTP), 7891 (SOCKS5), or 7892 (Mixed)
|
|
||||||
4. Make sure Tailscale is connected (required to reach the proxy server)
|
|
||||||
|
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
# SSH Tunnel Workaround for iPhone Proxy
|
|
||||||
|
|
||||||
## The Problem
|
|
||||||
Oracle Cloud Security List blocks proxy ports, and you don't have console access right now.
|
|
||||||
|
|
||||||
## Solution: SSH Tunnel via Your Mac
|
|
||||||
|
|
||||||
Since SSH (port 22) is already open, we can use it to tunnel proxy traffic!
|
|
||||||
|
|
||||||
### Step 1: Create SSH Tunnel on Your Mac
|
|
||||||
|
|
||||||
Open Terminal on your Mac and run:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ssh -L 7890:127.0.0.1:7890 -N server2
|
|
||||||
```
|
|
||||||
|
|
||||||
Or run in background:
|
|
||||||
```bash
|
|
||||||
ssh -f -N -L 7890:127.0.0.1:7890 server2
|
|
||||||
```
|
|
||||||
|
|
||||||
This creates a tunnel: `Your Mac:7890` → `SSH` → `server2:7890`
|
|
||||||
|
|
||||||
### Step 2: Configure iPhone to Use Your Mac as Proxy
|
|
||||||
|
|
||||||
**Option A: If Mac and iPhone on Same Wi-Fi**
|
|
||||||
|
|
||||||
1. **On your Mac:**
|
|
||||||
- System Settings → Network → Wi-Fi → Details → TCP/IP
|
|
||||||
- Note your Mac's local IP (e.g., `192.168.1.100`)
|
|
||||||
|
|
||||||
2. **On iPhone:**
|
|
||||||
- Settings → Wi-Fi → ⓘ (next to your Wi-Fi network)
|
|
||||||
- Scroll to **HTTP Proxy** → **Manual**
|
|
||||||
- **Server:** `192.168.1.100` (your Mac's IP)
|
|
||||||
- **Port:** `7890`
|
|
||||||
- **Authentication:** Off (SSH tunnel doesn't need it, but Clash does)
|
|
||||||
|
|
||||||
**Wait - this won't work because Clash needs authentication...**
|
|
||||||
|
|
||||||
### Better Solution: Use SOCKS Proxy Over SSH
|
|
||||||
|
|
||||||
Actually, SSH can create a SOCKS proxy directly!
|
|
||||||
|
|
||||||
### Step 3: Use SSH SOCKS Proxy (Better Method)
|
|
||||||
|
|
||||||
**On your Mac, run:**
|
|
||||||
```bash
|
|
||||||
ssh -D 1080 -N server2
|
|
||||||
```
|
|
||||||
|
|
||||||
This creates a SOCKS5 proxy on your Mac at `127.0.0.1:1080`
|
|
||||||
|
|
||||||
**Then on iPhone (same Wi-Fi):**
|
|
||||||
- Settings → Wi-Fi → ⓘ → HTTP Proxy → Manual
|
|
||||||
- **Server:** `192.168.1.100` (your Mac's IP)
|
|
||||||
- **Port:** `1080`
|
|
||||||
- **Type:** SOCKS5 (if option available)
|
|
||||||
|
|
||||||
**But iOS HTTP Proxy doesn't support SOCKS5...**
|
|
||||||
|
|
||||||
### Best Workaround: Use a Proxy App on Mac
|
|
||||||
|
|
||||||
Install a local proxy server on your Mac that:
|
|
||||||
1. Connects to server2 via SSH tunnel
|
|
||||||
2. Provides HTTP proxy for iPhone
|
|
||||||
|
|
||||||
### Alternative: Use Tailscale (If Available)
|
|
||||||
|
|
||||||
If you can use Tailscale:
|
|
||||||
1. Enable Tailscale VPN on iPhone
|
|
||||||
2. Configure Shadowrocket to use: `100.70.115.1:7890`
|
|
||||||
3. This bypasses Oracle Cloud firewall
|
|
||||||
|
|
||||||
### Simplest Workaround: Keep SSH Tunnel + Use Mac as Bridge
|
|
||||||
|
|
||||||
1. **On Mac:** Create SSH tunnel to server2's Clash
|
|
||||||
2. **On Mac:** Run a local proxy server that iPhone can connect to
|
|
||||||
3. **On iPhone:** Connect to Mac's proxy
|
|
||||||
|
|
||||||
Let me create a script for this...
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.4 KiB |
@@ -1,125 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Move Small Files Test - Start with smallest files first
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Move Small Files Test ==="
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
NAS_PATH="/Volumes/Download/temp documents from MAc"
|
|
||||||
DOCS_PATH="$HOME/Documents"
|
|
||||||
|
|
||||||
# Check NAS is mounted
|
|
||||||
if [ ! -d "$NAS_PATH" ]; then
|
|
||||||
echo "⚠️ NAS not mounted at: $NAS_PATH"
|
|
||||||
echo " Please check your mount point"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check current space
|
|
||||||
FREE_SPACE=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB=$(echo "scale=2; $FREE_SPACE / 1024 / 1024" | bc)
|
|
||||||
echo "Current free space: ${FREE_SPACE_GB}GB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Create destination
|
|
||||||
mkdir -p "$NAS_PATH/Documents"
|
|
||||||
|
|
||||||
echo "🔍 Finding smallest folders/files to move first..."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Get list sorted by size (smallest first)
|
|
||||||
du -h -d 1 "$DOCS_PATH" 2>/dev/null | sort -h | while read size item; do
|
|
||||||
# Skip the total line
|
|
||||||
if [ "$item" = "$DOCS_PATH" ]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
FOLDER_NAME=$(basename "$item")
|
|
||||||
|
|
||||||
# Skip if it's not a directory
|
|
||||||
if [ ! -d "$item" ]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Show what we found
|
|
||||||
echo "Found: $FOLDER_NAME ($size)"
|
|
||||||
done
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "📦 Moving smallest items first (under 1GB)..."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
MOVED_COUNT=0
|
|
||||||
|
|
||||||
# Move items under 1GB first
|
|
||||||
du -h -d 1 "$DOCS_PATH" 2>/dev/null | sort -h | while read size item; do
|
|
||||||
# Skip the total line
|
|
||||||
if [ "$item" = "$DOCS_PATH" ]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Skip if not a directory
|
|
||||||
if [ ! -d "$item" ]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
FOLDER_NAME=$(basename "$item")
|
|
||||||
|
|
||||||
# Check if size is under 1GB (look for M or K, not G)
|
|
||||||
if echo "$size" | grep -qE "[0-9]+[MK]"; then
|
|
||||||
echo "Moving: $FOLDER_NAME ($size)..."
|
|
||||||
|
|
||||||
if mv -v "$item" "$NAS_PATH/Documents/" 2>&1 | tail -3; then
|
|
||||||
echo " ✅ Successfully moved"
|
|
||||||
MOVED_COUNT=$((MOVED_COUNT + 1))
|
|
||||||
|
|
||||||
# Show progress
|
|
||||||
REMAINING=$(du -sh "$DOCS_PATH" 2>/dev/null | awk '{print $1}')
|
|
||||||
MOVED=$(du -sh "$NAS_PATH/Documents" 2>/dev/null | awk '{print $1}')
|
|
||||||
FREE_NOW=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_NOW_GB=$(echo "scale=2; $FREE_NOW / 1024 / 1024" | bc)
|
|
||||||
|
|
||||||
echo " Progress: $MOVED on NAS, $REMAINING remaining"
|
|
||||||
echo " Free space: ${FREE_NOW_GB}GB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Ask to continue after a few moves
|
|
||||||
if [ $MOVED_COUNT -ge 3 ]; then
|
|
||||||
read -p " Continue with more small files? (y/n) " -n 1 -r
|
|
||||||
echo ""
|
|
||||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
||||||
echo " Stopped. Run again to continue."
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
MOVED_COUNT=0
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo " ⚠️ Error moving $FOLDER_NAME"
|
|
||||||
echo " Continuing with next..."
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "📊 Summary:"
|
|
||||||
REMAINING=$(du -sh "$DOCS_PATH" 2>/dev/null | awk '{print $1}')
|
|
||||||
MOVED=$(du -sh "$NAS_PATH/Documents" 2>/dev/null | awk '{print $1}')
|
|
||||||
FREE_NOW=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_NOW_GB=$(echo "scale=2; $FREE_NOW / 1024 / 1024" | bc)
|
|
||||||
|
|
||||||
echo " Moved to NAS: $MOVED"
|
|
||||||
echo " Remaining: $REMAINING"
|
|
||||||
echo " Free space now: ${FREE_NOW_GB}GB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
if [ "$REMAINING" != "0B" ] && [ -n "$REMAINING" ]; then
|
|
||||||
echo "✅ Test successful! You can now:"
|
|
||||||
echo " 1. Run this script again to move more small files"
|
|
||||||
echo " 2. Or move larger files manually"
|
|
||||||
echo " 3. Or use: ./safe_move_documents.sh for automated chunked moves"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
# Oracle Cloud Console - Open Proxy Ports
|
|
||||||
|
|
||||||
## Step-by-Step Instructions
|
|
||||||
|
|
||||||
### Step 1: Find Your VCN
|
|
||||||
From the screenshot, you have multiple VCNs. We need to find which one your server2 instance uses.
|
|
||||||
|
|
||||||
**Option A: Check from server2**
|
|
||||||
```bash
|
|
||||||
ssh server2 'ip addr show ens3 | grep "inet "'
|
|
||||||
```
|
|
||||||
This will show the IP (e.g., 10.0.0.100), which matches VCN CIDR 10.0.0.0/16.
|
|
||||||
|
|
||||||
**Option B: Check instance details**
|
|
||||||
- Go to **Compute** → **Instances**
|
|
||||||
- Find your server2 instance
|
|
||||||
- Click on it
|
|
||||||
- Check the **VCN** or **Subnet** it's attached to
|
|
||||||
|
|
||||||
### Step 2: Open the VCN
|
|
||||||
1. Click on the **VCN name** (e.g., "vcn-20250609-0221") that matches your instance
|
|
||||||
2. This opens the VCN details page
|
|
||||||
|
|
||||||
### Step 3: Navigate to Security Lists
|
|
||||||
1. In the VCN details page, look for **"Security Lists"** in the left sidebar or Resources section
|
|
||||||
2. Click on **"Security Lists"**
|
|
||||||
3. You'll see a list of security lists (usually "Default Security List for vcn-...")
|
|
||||||
|
|
||||||
### Step 4: Edit the Security List
|
|
||||||
1. Click on the **Default Security List** (or the one attached to your subnet)
|
|
||||||
2. Click **"Edit All Rules"** or **"Add Ingress Rules"**
|
|
||||||
|
|
||||||
### Step 5: Add Ingress Rules
|
|
||||||
Add these 4 rules (one for each port):
|
|
||||||
|
|
||||||
**Rule 1: HTTP Proxy (7890)**
|
|
||||||
- **Source Type:** CIDR
|
|
||||||
- **Source CIDR:** `0.0.0.0/0` (or your IP for better security)
|
|
||||||
- **IP Protocol:** TCP
|
|
||||||
- **Destination Port Range:** `7890`
|
|
||||||
- **Description:** `Clash HTTP Proxy`
|
|
||||||
|
|
||||||
**Rule 2: SOCKS5 Proxy (7891)**
|
|
||||||
- **Source Type:** CIDR
|
|
||||||
- **Source CIDR:** `0.0.0.0/0`
|
|
||||||
- **IP Protocol:** TCP
|
|
||||||
- **Destination Port Range:** `7891`
|
|
||||||
- **Description:** `Clash SOCKS5 Proxy`
|
|
||||||
|
|
||||||
**Rule 3: Mixed Proxy (7892)**
|
|
||||||
- **Source Type:** CIDR
|
|
||||||
- **Source CIDR:** `0.0.0.0/0`
|
|
||||||
- **IP Protocol:** TCP
|
|
||||||
- **Destination Port Range:** `7892`
|
|
||||||
- **Description:** `Clash Mixed Proxy`
|
|
||||||
|
|
||||||
**Rule 4: Web UI (9090)**
|
|
||||||
- **Source Type:** CIDR
|
|
||||||
- **Source CIDR:** `0.0.0.0/0`
|
|
||||||
- **IP Protocol:** TCP
|
|
||||||
- **Destination Port Range:** `9090`
|
|
||||||
- **Description:** `Clash Web UI`
|
|
||||||
|
|
||||||
### Step 6: Save
|
|
||||||
1. Click **"Save Changes"** or **"Add Ingress Rules"**
|
|
||||||
2. Wait 30-60 seconds for rules to propagate
|
|
||||||
|
|
||||||
### Step 7: Test
|
|
||||||
After adding rules, test from your iPhone:
|
|
||||||
- Open Shadowrocket
|
|
||||||
- Add server: `158.101.140.85:7890`
|
|
||||||
- Username: `proxy_user`
|
|
||||||
- Password: `Cs7yBx1Rh9oK`
|
|
||||||
- Test connection
|
|
||||||
|
|
||||||
## Security Note
|
|
||||||
|
|
||||||
Using `0.0.0.0/0` allows access from anywhere. For better security:
|
|
||||||
- Use your home IP: `YOUR_IP/32`
|
|
||||||
- Or use a VPN IP range
|
|
||||||
- The proxy has authentication, so it's somewhat protected
|
|
||||||
|
|
||||||
## Quick Navigation Path
|
|
||||||
|
|
||||||
1. **Networking** → **Virtual Cloud Networks**
|
|
||||||
2. Click your VCN (the one with 10.0.0.0/16)
|
|
||||||
3. **Security Lists** (left sidebar or Resources)
|
|
||||||
4. Click **Default Security List**
|
|
||||||
5. **Add Ingress Rules**
|
|
||||||
6. Add 4 rules (ports 7890, 7891, 7892, 9090)
|
|
||||||
7. **Save**
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
**Can't find Security Lists?**
|
|
||||||
- Make sure you're in the VCN details page
|
|
||||||
- Look in the left sidebar under "Resources"
|
|
||||||
- Or check the "Resources" tab in the main content area
|
|
||||||
|
|
||||||
**Rules not working?**
|
|
||||||
- Wait 1-2 minutes for propagation
|
|
||||||
- Check that you added rules to the correct Security List
|
|
||||||
- Verify the Security List is attached to your subnet
|
|
||||||
- Check instance's subnet assignment
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Safe Move Documents - Move in smaller chunks to avoid getting stuck
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Safe Move Documents ==="
|
|
||||||
echo ""
|
|
||||||
echo "Moving large folders can get stuck. This script moves in smaller chunks."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
NAS_PATH="/Volumes/Download/temp documents from MAc"
|
|
||||||
DOCS_PATH="$HOME/Documents"
|
|
||||||
|
|
||||||
# Check if NAS is mounted
|
|
||||||
if [ ! -d "$NAS_PATH" ]; then
|
|
||||||
echo "⚠️ NAS path not found: $NAS_PATH"
|
|
||||||
echo ""
|
|
||||||
echo "Please check your NAS mount point:"
|
|
||||||
ls -la /Volumes/ | grep -i "download\|ds224"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "📊 Current Status:"
|
|
||||||
DOCS_SIZE=$(du -sh "$DOCS_PATH" 2>/dev/null | awk '{print $1}')
|
|
||||||
echo " Documents size: $DOCS_SIZE"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check what's already moved
|
|
||||||
if [ -d "$NAS_PATH/Documents" ]; then
|
|
||||||
MOVED_SIZE=$(du -sh "$NAS_PATH/Documents" 2>/dev/null | awk '{print $1}')
|
|
||||||
echo " Already on NAS: $MOVED_SIZE"
|
|
||||||
echo ""
|
|
||||||
echo " ⚠️ Documents folder already exists on NAS!"
|
|
||||||
echo " The previous move may have partially completed."
|
|
||||||
echo ""
|
|
||||||
read -p " Continue moving remaining files? (y/n) " -n 1 -r
|
|
||||||
echo ""
|
|
||||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "🔍 Analyzing Documents folder..."
|
|
||||||
echo " Finding largest subfolders to move first..."
|
|
||||||
du -h -d 1 "$DOCS_PATH" 2>/dev/null | sort -hr | head -10
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "📦 Strategy: Move in smaller chunks"
|
|
||||||
echo ""
|
|
||||||
echo "This will:"
|
|
||||||
echo " 1. Move largest subfolders one at a time"
|
|
||||||
echo " 2. Show progress after each move"
|
|
||||||
echo " 3. Allow you to stop if needed"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
read -p "Proceed with chunked move? (y/n) " -n 1 -r
|
|
||||||
echo ""
|
|
||||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create destination
|
|
||||||
mkdir -p "$NAS_PATH/Documents"
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "🚚 Moving in chunks..."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Get list of subfolders, sorted by size
|
|
||||||
du -h -d 1 "$DOCS_PATH" 2>/dev/null | sort -hr | while read size folder; do
|
|
||||||
# Skip the total line
|
|
||||||
if [ "$folder" = "$DOCS_PATH" ]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
FOLDER_NAME=$(basename "$folder")
|
|
||||||
|
|
||||||
# Skip if it's a file (not a directory)
|
|
||||||
if [ ! -d "$folder" ]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Moving: $FOLDER_NAME ($size)..."
|
|
||||||
|
|
||||||
# Move with verbose output
|
|
||||||
if mv -v "$folder" "$NAS_PATH/Documents/" 2>&1 | head -5; then
|
|
||||||
echo " ✅ Moved successfully"
|
|
||||||
else
|
|
||||||
echo " ⚠️ Error moving $FOLDER_NAME"
|
|
||||||
echo " Continuing with next folder..."
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Show progress
|
|
||||||
REMAINING=$(du -sh "$DOCS_PATH" 2>/dev/null | awk '{print $1}')
|
|
||||||
MOVED=$(du -sh "$NAS_PATH/Documents" 2>/dev/null | awk '{print $1}')
|
|
||||||
echo " Progress: $MOVED moved, $REMAINING remaining"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Ask to continue after each large folder
|
|
||||||
if echo "$size" | grep -qE "[0-9]+G"; then
|
|
||||||
read -p " Continue? (y/n) " -n 1 -r
|
|
||||||
echo ""
|
|
||||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
||||||
echo " Stopped. You can resume later."
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "📊 Final Status:"
|
|
||||||
REMAINING=$(du -sh "$DOCS_PATH" 2>/dev/null | awk '{print $1}')
|
|
||||||
MOVED=$(du -sh "$NAS_PATH/Documents" 2>/dev/null | awk '{print $1}')
|
|
||||||
echo " Moved to NAS: $MOVED"
|
|
||||||
echo " Remaining: $REMAINING"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
if [ "$REMAINING" != "0B" ] && [ -n "$REMAINING" ]; then
|
|
||||||
echo "⚠️ Some files remain. You can:"
|
|
||||||
echo " 1. Run this script again to continue"
|
|
||||||
echo " 2. Manually move remaining files"
|
|
||||||
echo " 3. Leave them if they're small"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
@@ -1,222 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Setup Clash Meta proxy server on server2
|
|
||||||
# Clash Meta is more actively maintained than original Clash
|
|
||||||
|
|
||||||
echo "=== Setting up Clash Meta proxy server on server2 ==="
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
ssh server2 << 'EOF'
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# Get Tailscale IP
|
|
||||||
TAILSCALE_IP=$(tailscale ip -4)
|
|
||||||
echo "Tailscale IP: $TAILSCALE_IP"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Detect architecture
|
|
||||||
ARCH=$(uname -m)
|
|
||||||
case $ARCH in
|
|
||||||
x86_64) CLASH_ARCH="amd64" ;;
|
|
||||||
aarch64|arm64) CLASH_ARCH="arm64" ;;
|
|
||||||
*) echo "Unsupported architecture: $ARCH"; exit 1 ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Create directories
|
|
||||||
CLASH_DIR="$HOME/clash-meta"
|
|
||||||
mkdir -p "$CLASH_DIR"
|
|
||||||
mkdir -p ~/.config/clash-meta
|
|
||||||
cd "$CLASH_DIR"
|
|
||||||
|
|
||||||
# Download Clash Meta
|
|
||||||
echo "Downloading Clash Meta..."
|
|
||||||
CLASH_VERSION="v1.18.0"
|
|
||||||
CLASH_FILE="clash.meta-linux-${CLASH_ARCH}-${CLASH_VERSION}"
|
|
||||||
|
|
||||||
if wget -q "https://github.com/MetaCubeX/mihomo/releases/download/${CLASH_VERSION}/${CLASH_FILE}.gz" -O clash.gz; then
|
|
||||||
gunzip -f clash.gz
|
|
||||||
mv "$CLASH_FILE" clash
|
|
||||||
chmod +x clash
|
|
||||||
echo "✓ Clash Meta downloaded"
|
|
||||||
else
|
|
||||||
echo "Failed to download Clash Meta. Trying alternative method..."
|
|
||||||
# Try downloading from release page
|
|
||||||
wget -q "https://github.com/MetaCubeX/mihomo/releases/latest/download/mihomo-linux-${CLASH_ARCH}.gz" -O clash.gz 2>/dev/null || \
|
|
||||||
wget -q "https://github.com/MetaCubeX/mihomo/releases/download/v1.18.0/mihomo-linux-${CLASH_ARCH}.gz" -O clash.gz
|
|
||||||
gunzip -f clash.gz
|
|
||||||
mv mihomo-linux-${CLASH_ARCH} clash 2>/dev/null || mv mihomo clash
|
|
||||||
chmod +x clash
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Verify installation
|
|
||||||
if [ -f ./clash ]; then
|
|
||||||
./clash -v || echo "Clash binary ready"
|
|
||||||
else
|
|
||||||
echo "✗ Clash binary not found"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create Clash configuration
|
|
||||||
echo "Creating configuration..."
|
|
||||||
cat > ~/.config/clash-meta/config.yaml << CONFIG
|
|
||||||
# Clash Meta configuration for server2 proxy
|
|
||||||
port: 7890
|
|
||||||
socks-port: 7891
|
|
||||||
mixed-port: 7892
|
|
||||||
allow-lan: true
|
|
||||||
bind-address: '*'
|
|
||||||
mode: rule
|
|
||||||
log-level: info
|
|
||||||
ipv6: false
|
|
||||||
external-controller: 0.0.0.0:9090
|
|
||||||
external-ui: ui
|
|
||||||
|
|
||||||
# DNS
|
|
||||||
dns:
|
|
||||||
enable: true
|
|
||||||
listen: 0.0.0.0:53
|
|
||||||
enhanced-mode: fake-ip
|
|
||||||
fake-ip-range: 198.18.0.1/16
|
|
||||||
nameserver:
|
|
||||||
- 8.8.8.8
|
|
||||||
- 1.1.1.1
|
|
||||||
fallback:
|
|
||||||
- 8.8.4.4
|
|
||||||
- 1.0.0.1
|
|
||||||
fallback-filter:
|
|
||||||
geoip: true
|
|
||||||
geoip-code: CN
|
|
||||||
ipcidr:
|
|
||||||
- 240.0.0.0/4
|
|
||||||
|
|
||||||
# Proxy (direct connection)
|
|
||||||
proxies:
|
|
||||||
- name: "direct"
|
|
||||||
type: direct
|
|
||||||
|
|
||||||
# Proxy groups
|
|
||||||
proxy-groups:
|
|
||||||
- name: "Proxy"
|
|
||||||
type: select
|
|
||||||
proxies:
|
|
||||||
- direct
|
|
||||||
- name: "Auto"
|
|
||||||
type: select
|
|
||||||
proxies:
|
|
||||||
- direct
|
|
||||||
|
|
||||||
# Rules - route all traffic through direct connection
|
|
||||||
rules:
|
|
||||||
- MATCH,Proxy
|
|
||||||
|
|
||||||
# Experimental
|
|
||||||
experimental:
|
|
||||||
ignore-resolve-fail: true
|
|
||||||
sniff-tls-sni: true
|
|
||||||
CONFIG
|
|
||||||
|
|
||||||
# Download Clash dashboard UI
|
|
||||||
echo "Downloading Clash UI..."
|
|
||||||
cd ~/.config/clash-meta
|
|
||||||
if [ ! -d ui ]; then
|
|
||||||
wget -q https://github.com/haishanh/yacd/archive/gh-pages.zip -O ui.zip 2>/dev/null || \
|
|
||||||
wget -q https://github.com/haishanh/yacd/releases/latest/download/yacd.tar.xz -O yacd.tar.xz 2>/dev/null
|
|
||||||
if [ -f yacd.tar.xz ]; then
|
|
||||||
tar -xf yacd.tar.xz
|
|
||||||
mv public ui
|
|
||||||
rm yacd.tar.xz
|
|
||||||
elif [ -f ui.zip ]; then
|
|
||||||
unzip -q ui.zip
|
|
||||||
mv yacd-gh-pages ui
|
|
||||||
rm ui.zip
|
|
||||||
else
|
|
||||||
echo "UI download failed, but Clash will work without it"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create systemd service
|
|
||||||
echo "Creating systemd service..."
|
|
||||||
sudo tee /etc/systemd/system/clash-meta.service > /dev/null << SERVICE
|
|
||||||
[Unit]
|
|
||||||
Description=Clash Meta daemon
|
|
||||||
After=network.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
Restart=always
|
|
||||||
User=$USER
|
|
||||||
WorkingDirectory=$CLASH_DIR
|
|
||||||
ExecStart=$CLASH_DIR/clash -d $HOME/.config/clash-meta
|
|
||||||
Environment="HOME=$HOME"
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
SERVICE
|
|
||||||
|
|
||||||
# Reload systemd and start Clash
|
|
||||||
sudo systemctl daemon-reload
|
|
||||||
sudo systemctl enable clash-meta
|
|
||||||
sudo systemctl restart clash-meta
|
|
||||||
|
|
||||||
# Wait for service to start
|
|
||||||
sleep 3
|
|
||||||
|
|
||||||
# Check status
|
|
||||||
if sudo systemctl is-active --quiet clash-meta; then
|
|
||||||
echo ""
|
|
||||||
echo "✓ Clash Meta is running!"
|
|
||||||
echo ""
|
|
||||||
echo "=== Configuration Summary ==="
|
|
||||||
echo "HTTP Proxy: $TAILSCALE_IP:7890"
|
|
||||||
echo "SOCKS5 Proxy: $TAILSCALE_IP:7891"
|
|
||||||
echo "Mixed Proxy (HTTP+SOCKS5): $TAILSCALE_IP:7892"
|
|
||||||
echo "Web UI: http://$TAILSCALE_IP:9090/ui"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Configure firewall
|
|
||||||
echo "=== Firewall Configuration ==="
|
|
||||||
if command -v ufw >/dev/null 2>&1 && sudo ufw status | grep -q "Status: active"; then
|
|
||||||
echo "Configuring UFW..."
|
|
||||||
sudo ufw allow 7890/tcp comment "Clash HTTP"
|
|
||||||
sudo ufw allow 7891/tcp comment "Clash SOCKS5"
|
|
||||||
sudo ufw allow 7892/tcp comment "Clash Mixed"
|
|
||||||
sudo ufw allow 9090/tcp comment "Clash Web UI"
|
|
||||||
sudo ufw allow 53/udp comment "Clash DNS"
|
|
||||||
else
|
|
||||||
echo "UFW not active. If using iptables, ensure ports 7890, 7891, 7892, 9090, 53 are open."
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "=== Client Configuration ==="
|
|
||||||
echo "For Clash clients, configure:"
|
|
||||||
echo " Type: HTTP"
|
|
||||||
echo " Server: $TAILSCALE_IP"
|
|
||||||
echo " Port: 7890"
|
|
||||||
echo ""
|
|
||||||
echo "Or use Mixed port (supports both HTTP and SOCKS5):"
|
|
||||||
echo " Server: $TAILSCALE_IP"
|
|
||||||
echo " Port: 7892"
|
|
||||||
|
|
||||||
else
|
|
||||||
echo "✗ Clash Meta failed to start"
|
|
||||||
echo "Check logs: sudo journalctl -u clash-meta -n 50"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
EOF
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "=== Setup Complete ==="
|
|
||||||
echo ""
|
|
||||||
echo "Commands:"
|
|
||||||
echo " Status: ssh server2 'sudo systemctl status clash-meta'"
|
|
||||||
echo " Logs: ssh server2 'sudo journalctl -u clash-meta -f'"
|
|
||||||
echo " Restart: ssh server2 'sudo systemctl restart clash-meta'"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,176 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Setup Clash proxy server on server2
|
|
||||||
# This will install Clash and configure it to work with Tailscale
|
|
||||||
|
|
||||||
echo "=== Setting up Clash proxy server on server2 ==="
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
ssh server2 << 'EOF'
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# Get Tailscale IP
|
|
||||||
TAILSCALE_IP=$(tailscale ip -4)
|
|
||||||
echo "Tailscale IP: $TAILSCALE_IP"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Create clash directory
|
|
||||||
CLASH_DIR="$HOME/clash"
|
|
||||||
mkdir -p "$CLASH_DIR"
|
|
||||||
cd "$CLASH_DIR"
|
|
||||||
|
|
||||||
# Download Clash (latest version)
|
|
||||||
echo "Downloading Clash..."
|
|
||||||
CLASH_VERSION="v1.20.0"
|
|
||||||
ARCH="amd64"
|
|
||||||
if [ "$(uname -m)" = "aarch64" ] || [ "$(uname -m)" = "arm64" ]; then
|
|
||||||
ARCH="arm64"
|
|
||||||
fi
|
|
||||||
|
|
||||||
wget -q "https://github.com/Dreamacro/clash/releases/download/${CLASH_VERSION}/clash-linux-${ARCH}-${CLASH_VERSION}.gz" -O clash.gz
|
|
||||||
gunzip -f clash.gz
|
|
||||||
chmod +x clash
|
|
||||||
|
|
||||||
# Create config directory
|
|
||||||
mkdir -p ~/.config/clash
|
|
||||||
|
|
||||||
# Create Clash configuration file
|
|
||||||
cat > ~/.config/clash/config.yaml << CONFIG
|
|
||||||
# Clash configuration for server2 proxy
|
|
||||||
port: 7890
|
|
||||||
socks-port: 7891
|
|
||||||
allow-lan: true
|
|
||||||
bind-address: '*'
|
|
||||||
mode: rule
|
|
||||||
log-level: info
|
|
||||||
external-controller: 0.0.0.0:9090
|
|
||||||
external-ui: /root/.config/clash/ui
|
|
||||||
|
|
||||||
# DNS
|
|
||||||
dns:
|
|
||||||
enable: true
|
|
||||||
listen: 0.0.0.0:53
|
|
||||||
enhanced-mode: fake-ip
|
|
||||||
nameserver:
|
|
||||||
- 8.8.8.8
|
|
||||||
- 1.1.1.1
|
|
||||||
fallback:
|
|
||||||
- 8.8.4.4
|
|
||||||
- 1.0.0.1
|
|
||||||
|
|
||||||
# Proxy (direct connection - no upstream proxy needed)
|
|
||||||
proxies:
|
|
||||||
- name: "direct"
|
|
||||||
type: direct
|
|
||||||
|
|
||||||
# Proxy groups
|
|
||||||
proxy-groups:
|
|
||||||
- name: "Proxy"
|
|
||||||
type: select
|
|
||||||
proxies:
|
|
||||||
- direct
|
|
||||||
- name: "Auto"
|
|
||||||
type: select
|
|
||||||
proxies:
|
|
||||||
- direct
|
|
||||||
|
|
||||||
# Rules - route all traffic through direct connection
|
|
||||||
rules:
|
|
||||||
- MATCH,Proxy
|
|
||||||
|
|
||||||
# Experimental features
|
|
||||||
experimental:
|
|
||||||
ignore-resolve-fail: true
|
|
||||||
CONFIG
|
|
||||||
|
|
||||||
# Download Clash dashboard UI (optional but useful)
|
|
||||||
echo "Downloading Clash UI..."
|
|
||||||
if [ ! -d ~/.config/clash/ui ]; then
|
|
||||||
cd ~/.config/clash
|
|
||||||
wget -q https://github.com/haishanh/yacd/releases/latest/download/yacd.tar.xz -O yacd.tar.xz
|
|
||||||
tar -xf yacd.tar.xz
|
|
||||||
mv public ui
|
|
||||||
rm yacd.tar.xz
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create systemd service
|
|
||||||
echo "Creating systemd service..."
|
|
||||||
sudo tee /etc/systemd/system/clash.service > /dev/null << SERVICE
|
|
||||||
[Unit]
|
|
||||||
Description=Clash daemon
|
|
||||||
After=network.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
Restart=always
|
|
||||||
User=$USER
|
|
||||||
ExecStart=$CLASH_DIR/clash -d $HOME/.config/clash
|
|
||||||
Environment="HOME=$HOME"
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
SERVICE
|
|
||||||
|
|
||||||
# Reload systemd and start Clash
|
|
||||||
sudo systemctl daemon-reload
|
|
||||||
sudo systemctl enable clash
|
|
||||||
sudo systemctl restart clash
|
|
||||||
|
|
||||||
# Wait a moment for service to start
|
|
||||||
sleep 2
|
|
||||||
|
|
||||||
# Check status
|
|
||||||
if sudo systemctl is-active --quiet clash; then
|
|
||||||
echo ""
|
|
||||||
echo "✓ Clash is running!"
|
|
||||||
echo ""
|
|
||||||
echo "=== Configuration Summary ==="
|
|
||||||
echo "HTTP Proxy: $TAILSCALE_IP:7890"
|
|
||||||
echo "SOCKS5 Proxy: $TAILSCALE_IP:7891"
|
|
||||||
echo "Web UI: http://$TAILSCALE_IP:9090/ui"
|
|
||||||
echo ""
|
|
||||||
echo "=== Firewall Configuration ==="
|
|
||||||
echo "Checking firewall rules..."
|
|
||||||
|
|
||||||
# Check if ufw is active
|
|
||||||
if sudo ufw status | grep -q "Status: active"; then
|
|
||||||
echo "UFW is active. Adding rules..."
|
|
||||||
sudo ufw allow 7890/tcp comment "Clash HTTP"
|
|
||||||
sudo ufw allow 7891/tcp comment "Clash SOCKS5"
|
|
||||||
sudo ufw allow 9090/tcp comment "Clash Web UI"
|
|
||||||
sudo ufw allow 53/udp comment "Clash DNS"
|
|
||||||
else
|
|
||||||
echo "UFW is not active. If using iptables, you may need to add rules manually."
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "=== Client Configuration ==="
|
|
||||||
echo "For Clash clients, use this proxy:"
|
|
||||||
echo " Type: HTTP"
|
|
||||||
echo " Server: $TAILSCALE_IP"
|
|
||||||
echo " Port: 7890"
|
|
||||||
echo ""
|
|
||||||
echo "Or SOCKS5:"
|
|
||||||
echo " Type: SOCKS5"
|
|
||||||
echo " Server: $TAILSCALE_IP"
|
|
||||||
echo " Port: 7891"
|
|
||||||
else
|
|
||||||
echo "✗ Clash failed to start. Check logs with: sudo journalctl -u clash -n 50"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
EOF
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "=== Setup Complete ==="
|
|
||||||
echo ""
|
|
||||||
echo "To check Clash status: ssh server2 'sudo systemctl status clash'"
|
|
||||||
echo "To view logs: ssh server2 'sudo journalctl -u clash -f'"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Setup Mac as Proxy Bridge for iPhone
|
|
||||||
# This script sets up a local proxy on Mac that tunnels to server2
|
|
||||||
|
|
||||||
echo "=== Mac Proxy Bridge Setup ==="
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check if Python is available (for simple HTTP proxy)
|
|
||||||
if command -v python3 &> /dev/null; then
|
|
||||||
echo "Python3 found - creating simple proxy bridge..."
|
|
||||||
echo ""
|
|
||||||
echo "Run this command to start the bridge:"
|
|
||||||
echo ""
|
|
||||||
echo "python3 -m http.server 8080 &"
|
|
||||||
echo "ssh -L 7890:127.0.0.1:7890 -N server2 &"
|
|
||||||
echo ""
|
|
||||||
echo "But we need a proper HTTP proxy, not just a web server..."
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Better: Use socat or create a proper proxy
|
|
||||||
if command -v socat &> /dev/null; then
|
|
||||||
echo "socat found - can create proxy bridge"
|
|
||||||
echo ""
|
|
||||||
echo "Run:"
|
|
||||||
echo "ssh -L 7890:127.0.0.1:7890 -N server2 &"
|
|
||||||
echo "socat TCP-LISTEN:8080,fork,reuseaddr TCP:127.0.0.1:7890 &"
|
|
||||||
else
|
|
||||||
echo "Installing socat for proxy bridging..."
|
|
||||||
echo "brew install socat"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "=== Alternative: Use SSH Dynamic Port Forwarding ==="
|
|
||||||
echo ""
|
|
||||||
echo "Run this on your Mac:"
|
|
||||||
echo "ssh -D 1080 -N server2"
|
|
||||||
echo ""
|
|
||||||
echo "This creates a SOCKS5 proxy on localhost:1080"
|
|
||||||
echo "But iPhone HTTP Proxy doesn't support SOCKS5 directly..."
|
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
# Shadowrocket Setup for Cellular Data
|
|
||||||
|
|
||||||
## The Solution
|
|
||||||
|
|
||||||
Since iOS doesn't support HTTP proxy for cellular data, you need to use **Shadowrocket VPN mode**. Here's how:
|
|
||||||
|
|
||||||
## Setup Steps
|
|
||||||
|
|
||||||
### Step 1: Configure Server (Already Done ✅)
|
|
||||||
- Clash now listens on all interfaces
|
|
||||||
- Firewall allows Tailscale network (100.x.x.x) only
|
|
||||||
- Proxy accessible at: `100.70.115.1:7890`
|
|
||||||
|
|
||||||
### Step 2: On Your iPhone
|
|
||||||
|
|
||||||
**Option A: Use Shadowrocket VPN Mode (Recommended for Cellular)**
|
|
||||||
|
|
||||||
1. **Disable Tailscale VPN:**
|
|
||||||
- Open Tailscale app
|
|
||||||
- Toggle VPN OFF (but keep app installed/running)
|
|
||||||
- This frees up the VPN slot for Shadowrocket
|
|
||||||
|
|
||||||
2. **Configure Shadowrocket:**
|
|
||||||
- Open Shadowrocket
|
|
||||||
- Go to **Home** tab
|
|
||||||
- Tap **"+"** to add server
|
|
||||||
- Select **HTTP**
|
|
||||||
- Enter:
|
|
||||||
- **Address:** `100.70.115.1`
|
|
||||||
- **Port:** `7890`
|
|
||||||
- **Remark:** `server2-proxy`
|
|
||||||
- Tap **Done**
|
|
||||||
|
|
||||||
3. **Enable Shadowrocket:**
|
|
||||||
- Select `server2-proxy` in Home tab
|
|
||||||
- Toggle switch **ON**
|
|
||||||
- VPN icon should appear in status bar
|
|
||||||
|
|
||||||
4. **Test:**
|
|
||||||
- Open Safari
|
|
||||||
- Visit: https://api.ipify.org
|
|
||||||
- Should show: `158.101.140.85` (server2's IP)
|
|
||||||
- Works on both Wi-Fi and cellular! ✅
|
|
||||||
|
|
||||||
**How it works:**
|
|
||||||
- Shadowrocket creates a VPN connection
|
|
||||||
- It routes all traffic (Wi-Fi + cellular) through the proxy
|
|
||||||
- Traffic goes: iPhone → Shadowrocket VPN → Tailscale network → server2 proxy → Internet
|
|
||||||
|
|
||||||
**Note:** You'll lose direct Tailscale network access (can't SSH to other Tailscale devices), but proxy will work on both Wi-Fi and cellular.
|
|
||||||
|
|
||||||
### Option B: Keep Tailscale VPN, Use System Proxy (Wi-Fi Only)
|
|
||||||
|
|
||||||
If you need Tailscale network access:
|
|
||||||
|
|
||||||
1. **Keep Tailscale VPN ON**
|
|
||||||
2. **Don't use Shadowrocket VPN mode**
|
|
||||||
3. Configure system proxy for Wi-Fi:
|
|
||||||
- Settings → Wi-Fi → ⓘ → HTTP Proxy → Manual
|
|
||||||
- Server: `100.70.115.1`
|
|
||||||
- Port: `7890`
|
|
||||||
4. **Cellular won't work** with this method (iOS limitation)
|
|
||||||
|
|
||||||
## Recommendation
|
|
||||||
|
|
||||||
**Use Option A (Shadowrocket VPN mode)** if you:
|
|
||||||
- Need proxy on cellular data
|
|
||||||
- Don't need direct Tailscale network access while using proxy
|
|
||||||
- Want it to work everywhere
|
|
||||||
|
|
||||||
**Use Option B (System proxy)** if you:
|
|
||||||
- Only need proxy on Wi-Fi
|
|
||||||
- Need direct Tailscale network access
|
|
||||||
- Can live without cellular proxy
|
|
||||||
|
|
||||||
## Switching Between Modes
|
|
||||||
|
|
||||||
You can easily switch:
|
|
||||||
- **Need proxy on cellular?** → Disable Tailscale VPN, enable Shadowrocket VPN
|
|
||||||
- **Need Tailscale network?** → Disable Shadowrocket VPN, enable Tailscale VPN
|
|
||||||
- **Need both?** → Use system proxy on Wi-Fi (but no cellular proxy)
|
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
After setup:
|
|
||||||
1. Turn OFF Wi-Fi (use cellular only)
|
|
||||||
2. Open Safari
|
|
||||||
3. Visit: https://api.ipify.org
|
|
||||||
4. Should show server2's IP: `158.101.140.85`
|
|
||||||
5. If it shows your cellular IP, proxy isn't working
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
**Proxy not working on cellular?**
|
|
||||||
- Make sure Shadowrocket VPN is enabled (VPN icon in status bar)
|
|
||||||
- Check that server2 is online: `ssh server2 'sudo systemctl status clash-meta'`
|
|
||||||
- Verify Tailscale network is reachable (even with VPN off, the network should exist)
|
|
||||||
|
|
||||||
**Can't reach other Tailscale devices?**
|
|
||||||
- That's expected when Shadowrocket VPN is on
|
|
||||||
- Disable Shadowrocket VPN and enable Tailscale VPN when you need direct access
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,153 +0,0 @@
|
|||||||
# Shadowrocket Correct Setup - Working with Tailscale
|
|
||||||
|
|
||||||
## Understanding Shadowrocket Architecture
|
|
||||||
|
|
||||||
Shadowrocket works as a **local proxy server** on your iPhone:
|
|
||||||
- Apps connect to Shadowrocket's local proxy (127.0.0.1:80)
|
|
||||||
- Shadowrocket forwards traffic to your configured server (server2)
|
|
||||||
- This way it doesn't need VPN mode!
|
|
||||||
|
|
||||||
## Step-by-Step Setup
|
|
||||||
|
|
||||||
### Step 1: Add Server2 as a Server (NOT in Proxy Settings)
|
|
||||||
|
|
||||||
1. Open Shadowrocket app
|
|
||||||
2. Go to the **"Home"** tab (house icon at bottom)
|
|
||||||
3. Tap the **"+"** button in the top right corner
|
|
||||||
4. Select **"HTTP"** or **"HTTPS"**
|
|
||||||
5. Fill in:
|
|
||||||
- **Remark:** `server2-proxy`
|
|
||||||
- **Address:** `100.70.115.1` (your Tailscale IP)
|
|
||||||
- **Port:** `7890` (HTTP) or `7892` (Mixed)
|
|
||||||
- **Username:** (leave empty)
|
|
||||||
- **Password:** (leave empty)
|
|
||||||
6. Tap **"Done"**
|
|
||||||
|
|
||||||
### Step 2: Enable the Server
|
|
||||||
|
|
||||||
1. Go back to **"Home"** tab
|
|
||||||
2. You should see `server2-proxy` in the server list
|
|
||||||
3. Tap on it to select it
|
|
||||||
4. Toggle the switch at the top to **ON**
|
|
||||||
|
|
||||||
### Step 3: Configure Proxy Settings (What You Saw)
|
|
||||||
|
|
||||||
The "Proxy Settings" you saw (127.0.0.1:80) is Shadowrocket's **local proxy** that apps connect to. You can configure it:
|
|
||||||
|
|
||||||
1. Go to **"Settings"** tab (gear icon)
|
|
||||||
2. Tap **"Proxy"**
|
|
||||||
3. In **"Proxy Settings"** section:
|
|
||||||
- **Proxy Type:** HTTP (or leave as is)
|
|
||||||
- **Proxy Port:** `80` (or any port, this is local)
|
|
||||||
- **Proxy Address:** `127.0.0.1` (localhost - this is correct)
|
|
||||||
|
|
||||||
**Important:** These settings are for Shadowrocket's LOCAL proxy. Your apps will connect to this, and Shadowrocket will forward to server2.
|
|
||||||
|
|
||||||
### Step 4: Configure Apps to Use Shadowrocket's Local Proxy
|
|
||||||
|
|
||||||
Now you need to tell your apps to use Shadowrocket's local proxy:
|
|
||||||
|
|
||||||
**Option A: System-Wide (Limited)**
|
|
||||||
1. Settings → Wi-Fi
|
|
||||||
2. Tap ⓘ next to your Wi-Fi
|
|
||||||
3. Scroll to **HTTP Proxy**
|
|
||||||
4. Select **Manual**
|
|
||||||
5. Enter:
|
|
||||||
- **Server:** `127.0.0.1` (or `localhost`)
|
|
||||||
- **Port:** `80` (or whatever you set in Proxy Settings)
|
|
||||||
6. Save
|
|
||||||
|
|
||||||
**Option B: Use Shadowrocket's VPN Mode (But Configured Correctly)**
|
|
||||||
|
|
||||||
Actually, Shadowrocket's "VPN mode" is how it intercepts traffic. Here's the trick:
|
|
||||||
|
|
||||||
1. In Shadowrocket **"Home"** tab
|
|
||||||
2. Make sure your `server2-proxy` is selected
|
|
||||||
3. Toggle the switch ON
|
|
||||||
4. **This will create a VPN connection** BUT it's Shadowrocket's VPN, not a conflict
|
|
||||||
5. Shadowrocket's VPN intercepts traffic and routes it through server2
|
|
||||||
|
|
||||||
**The key:** Shadowrocket's VPN mode is fine - it's a different VPN than Tailscale. However, iOS only allows ONE VPN at a time, so:
|
|
||||||
|
|
||||||
### Solution: Use Shadowrocket's VPN Mode (Disable Tailscale VPN)
|
|
||||||
|
|
||||||
Since iOS only allows one VPN:
|
|
||||||
1. **Disable Tailscale's VPN mode** (but keep Tailscale app running for network access)
|
|
||||||
2. **Enable Shadowrocket's VPN mode**
|
|
||||||
3. Shadowrocket will route through Tailscale's network to reach server2
|
|
||||||
|
|
||||||
Wait - that won't work because Tailscale needs VPN mode to provide network access...
|
|
||||||
|
|
||||||
### Better Solution: Use Proxy Chain Feature
|
|
||||||
|
|
||||||
Looking at your screenshot, I see **"Proxy Chain"** option! This might be the solution:
|
|
||||||
|
|
||||||
1. Go to **Settings** → **Proxy Chain**
|
|
||||||
2. Enable **"Enable Chain"** toggle
|
|
||||||
3. Configure:
|
|
||||||
- **Type:** HTTP
|
|
||||||
- **Address:** `100.70.115.1`
|
|
||||||
- **Port:** `7890`
|
|
||||||
4. This might allow Shadowrocket to use Tailscale's network without VPN conflict
|
|
||||||
|
|
||||||
## Recommended Approach
|
|
||||||
|
|
||||||
Based on your screenshots, here's what to do:
|
|
||||||
|
|
||||||
### Method 1: Use Proxy Chain (Try This First)
|
|
||||||
|
|
||||||
1. **Keep Tailscale VPN ON**
|
|
||||||
2. In Shadowrocket:
|
|
||||||
- Go to **Settings** → **Proxy Chain**
|
|
||||||
- Enable **"Enable Chain"**
|
|
||||||
- Set Type: HTTP, Address: `100.70.115.1`, Port: `7890`
|
|
||||||
3. In Shadowrocket **Home** tab:
|
|
||||||
- Add a "Direct" or "Reject" server (or use existing)
|
|
||||||
- Enable Shadowrocket
|
|
||||||
4. Configure apps to use Shadowrocket's local proxy (127.0.0.1:80)
|
|
||||||
|
|
||||||
### Method 2: Use Shadowrocket VPN Mode (Disable Tailscale)
|
|
||||||
|
|
||||||
1. **Disable Tailscale VPN** (but app can stay installed)
|
|
||||||
2. In Shadowrocket **Home** tab:
|
|
||||||
- Add server2: `100.70.115.1:7890`
|
|
||||||
- Enable Shadowrocket VPN mode
|
|
||||||
3. Shadowrocket will handle routing
|
|
||||||
|
|
||||||
**Problem:** You'll lose direct Tailscale network access, but proxy will work.
|
|
||||||
|
|
||||||
### Method 3: Use System Proxy Settings
|
|
||||||
|
|
||||||
1. Keep Tailscale ON
|
|
||||||
2. Don't use Shadowrocket VPN mode
|
|
||||||
3. Configure system proxy:
|
|
||||||
- Settings → Wi-Fi → ⓘ → HTTP Proxy → Manual
|
|
||||||
- Server: `100.70.115.1`
|
|
||||||
- Port: `7890`
|
|
||||||
4. This works for some apps but not all
|
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
After setup:
|
|
||||||
1. Open Safari
|
|
||||||
2. Visit: https://api.ipify.org
|
|
||||||
3. Should show: `158.101.140.85` (server2's IP)
|
|
||||||
|
|
||||||
## Which Method Should You Use?
|
|
||||||
|
|
||||||
**Try Proxy Chain first** - it might allow both Tailscale and Shadowrocket to work together!
|
|
||||||
|
|
||||||
If that doesn't work, you'll need to choose:
|
|
||||||
- **Tailscale VPN** = Direct network access, but no proxy
|
|
||||||
- **Shadowrocket VPN** = Proxy works, but no direct Tailscale network
|
|
||||||
|
|
||||||
Let me know which method works for you!
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,136 +0,0 @@
|
|||||||
# Shadowrocket Proxy Mode Setup Guide
|
|
||||||
|
|
||||||
## Understanding Shadowrocket Modes
|
|
||||||
|
|
||||||
Shadowrocket has two main modes:
|
|
||||||
1. **VPN Mode (TUN Mode)** - Creates a VPN connection (conflicts with Tailscale)
|
|
||||||
2. **Proxy Mode** - Routes traffic through proxy without VPN (works with Tailscale) ✅ **Use This!**
|
|
||||||
|
|
||||||
## Reference Article
|
|
||||||
For additional details, see: https://privateproxy.me/blog/how-to-use-proxies-with-shadowrocket/
|
|
||||||
|
|
||||||
## Step-by-Step: Enable Proxy Mode
|
|
||||||
|
|
||||||
### Step 1: Install Shadowrocket
|
|
||||||
- Download from App Store (~$3)
|
|
||||||
- Open the app
|
|
||||||
|
|
||||||
### Step 2: Add Your Proxy Server
|
|
||||||
|
|
||||||
1. Open Shadowrocket app
|
|
||||||
2. Tap the **"+"** button in the top right corner
|
|
||||||
3. You'll see different server types - select **"HTTP"** or **"HTTPS"**
|
|
||||||
|
|
||||||
### Step 3: Configure Proxy Settings
|
|
||||||
|
|
||||||
Fill in the details:
|
|
||||||
- **Type:** HTTP (or HTTPS)
|
|
||||||
- **Remark:** `server2-proxy` (or any name you prefer)
|
|
||||||
- **Address:** `100.70.115.1` (your Tailscale IP)
|
|
||||||
- **Port:** `7890` (HTTP) or `7892` (Mixed port)
|
|
||||||
- **Username:** (leave empty)
|
|
||||||
- **Password:** (leave empty)
|
|
||||||
- **Method:** (leave as default)
|
|
||||||
|
|
||||||
4. Tap **"Done"** or **"Save"**
|
|
||||||
|
|
||||||
### Step 4: Enable Proxy Mode (NOT VPN Mode)
|
|
||||||
|
|
||||||
**This is the critical step!**
|
|
||||||
|
|
||||||
1. In Shadowrocket main screen, you'll see your proxy server listed
|
|
||||||
2. Tap on your proxy server to select it
|
|
||||||
3. **Important:** Look for these settings:
|
|
||||||
|
|
||||||
**Option A: Global Routing Mode**
|
|
||||||
- Tap the three dots (⋯) or "Edit" next to your proxy
|
|
||||||
- Look for **"Routing"** or **"Mode"** setting
|
|
||||||
- Select **"Proxy"** or **"Global Proxy"** (NOT "VPN" or "TUN")
|
|
||||||
|
|
||||||
**Option B: Settings Menu**
|
|
||||||
- Go to **Settings** (gear icon at bottom)
|
|
||||||
- Find **"Proxy"** or **"Routing"** section
|
|
||||||
- Enable **"Use Proxy"**
|
|
||||||
- Make sure **"VPN" mode is OFF** or **"TUN" mode is OFF**
|
|
||||||
- Select **"Proxy Mode"** instead
|
|
||||||
|
|
||||||
### Step 5: Enable the Connection
|
|
||||||
|
|
||||||
1. Go back to main screen
|
|
||||||
2. Find the toggle switch at the top
|
|
||||||
3. **Toggle it ON**
|
|
||||||
4. You should see a checkmark next to your proxy server
|
|
||||||
5. **Important:** You should NOT see a VPN icon in status bar (that means VPN mode is active)
|
|
||||||
|
|
||||||
### Step 6: Verify It's Working in Proxy Mode
|
|
||||||
|
|
||||||
**Check for VPN icon:**
|
|
||||||
- ✅ **Correct:** No VPN icon in status bar = Proxy mode active
|
|
||||||
- ❌ **Wrong:** VPN icon appears = VPN mode active (will conflict with Tailscale)
|
|
||||||
|
|
||||||
**Test the connection:**
|
|
||||||
1. Open Safari
|
|
||||||
2. Visit: https://api.ipify.org
|
|
||||||
3. Should show: `158.101.140.85` (server2's IP)
|
|
||||||
|
|
||||||
## Alternative: Using Configuration File
|
|
||||||
|
|
||||||
If the UI is confusing, you can use a config file:
|
|
||||||
|
|
||||||
1. In Shadowrocket, tap **"Config"** tab at bottom
|
|
||||||
2. Tap **"+"** to add new config
|
|
||||||
3. Create a config with:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
# Shadowrocket Config
|
|
||||||
[Proxy]
|
|
||||||
server2 = http, 100.70.115.1, 7890
|
|
||||||
|
|
||||||
[Rule]
|
|
||||||
FINAL,server2
|
|
||||||
```
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Problem: VPN icon appears (conflicts with Tailscale)
|
|
||||||
**Solution:**
|
|
||||||
- Go to Settings → Routing
|
|
||||||
- Disable "TUN Mode" or "VPN Mode"
|
|
||||||
- Enable "Proxy Mode" only
|
|
||||||
- Restart Shadowrocket
|
|
||||||
|
|
||||||
### Problem: Can't connect to proxy
|
|
||||||
**Check:**
|
|
||||||
1. Is Tailscale connected? (Required to reach 100.70.115.1)
|
|
||||||
2. Is server2 online? `ssh server2 'sudo systemctl status clash-meta'`
|
|
||||||
3. Try different port: 7890, 7891, or 7892
|
|
||||||
|
|
||||||
### Problem: Some apps don't work
|
|
||||||
**Solution:**
|
|
||||||
- Some iOS apps ignore system proxy
|
|
||||||
- You may need to use Shadowrocket's VPN mode for those apps
|
|
||||||
- But then you'll need to disable Tailscale temporarily
|
|
||||||
|
|
||||||
## Visual Guide Reference
|
|
||||||
|
|
||||||
Look for these in Shadowrocket:
|
|
||||||
- **"Proxy"** or **"HTTP Proxy"** option (use this)
|
|
||||||
- **"TUN"** or **"VPN"** option (avoid this when Tailscale is on)
|
|
||||||
- **"Global Proxy"** or **"Proxy Mode"** (this is what you want)
|
|
||||||
|
|
||||||
## Key Differences
|
|
||||||
|
|
||||||
| Mode | VPN Icon? | Works with Tailscale? | Use Case |
|
|
||||||
|------|-----------|----------------------|----------|
|
|
||||||
| **Proxy Mode** | ❌ No | ✅ Yes | Use this! |
|
|
||||||
| **VPN Mode** | ✅ Yes | ❌ No | Only when Tailscale is off |
|
|
||||||
|
|
||||||
## Quick Checklist
|
|
||||||
|
|
||||||
- [ ] Tailscale is ON and connected
|
|
||||||
- [ ] Added HTTP proxy: `100.70.115.1:7890`
|
|
||||||
- [ ] Enabled "Proxy Mode" (NOT VPN mode)
|
|
||||||
- [ ] Toggle switch is ON
|
|
||||||
- [ ] No VPN icon in status bar
|
|
||||||
- [ ] Test: Visit https://api.ipify.org shows server2 IP
|
|
||||||
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
# Shadowrocket Setup with Public IP (No Tailscale VPN Needed)
|
|
||||||
|
|
||||||
## ✅ Solution: Proxy Now Accessible via Public IP
|
|
||||||
|
|
||||||
The proxy is now configured to listen on the public IP, so you can use Shadowrocket **without** Tailscale VPN!
|
|
||||||
|
|
||||||
## Setup Steps
|
|
||||||
|
|
||||||
### Step 1: Get Proxy Credentials
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ssh server2 'cat ~/.clash_credentials.txt'
|
|
||||||
```
|
|
||||||
|
|
||||||
You'll see: `username:password`
|
|
||||||
|
|
||||||
### Step 2: Configure Shadowrocket on iPhone
|
|
||||||
|
|
||||||
1. **Disable Tailscale VPN** (Settings → Tailscale → toggle OFF)
|
|
||||||
- This frees up the VPN slot for Shadowrocket
|
|
||||||
|
|
||||||
2. **Open Shadowrocket**
|
|
||||||
- Go to **Home** tab
|
|
||||||
- Tap **"+"** to add server
|
|
||||||
|
|
||||||
3. **Add HTTP Proxy with Authentication:**
|
|
||||||
- **Type:** HTTP
|
|
||||||
- **Address:** `158.101.140.85` (server2's public IP)
|
|
||||||
- **Port:** `7890` (HTTP) or `7892` (Mixed)
|
|
||||||
- **Username:** (from credentials file)
|
|
||||||
- **Password:** (from credentials file)
|
|
||||||
- **Remark:** `server2-proxy`
|
|
||||||
|
|
||||||
4. **Enable Shadowrocket:**
|
|
||||||
- Select your proxy server
|
|
||||||
- Toggle switch **ON**
|
|
||||||
- VPN icon should appear in status bar
|
|
||||||
|
|
||||||
### Step 3: Test
|
|
||||||
|
|
||||||
1. Turn OFF Wi-Fi (use cellular only)
|
|
||||||
2. Open Safari
|
|
||||||
3. Visit: https://api.ipify.org
|
|
||||||
4. Should show: `158.101.140.85` (server2's IP) ✅
|
|
||||||
|
|
||||||
## Proxy Details
|
|
||||||
|
|
||||||
- **Public IP:** `158.101.140.85`
|
|
||||||
- **Ports:**
|
|
||||||
- `7890` - HTTP
|
|
||||||
- `7891` - SOCKS5
|
|
||||||
- `7892` - Mixed (HTTP + SOCKS5) - **Recommended**
|
|
||||||
- **Authentication:** Required (username/password)
|
|
||||||
|
|
||||||
## Security Notes
|
|
||||||
|
|
||||||
✅ **Protected by:**
|
|
||||||
- Username/password authentication
|
|
||||||
- Firewall rules (UFW active)
|
|
||||||
- Only proxy ports exposed (not SSH or other services)
|
|
||||||
|
|
||||||
⚠️ **Considerations:**
|
|
||||||
- Proxy is accessible from public internet
|
|
||||||
- Anyone with credentials can use it
|
|
||||||
- Monitor usage: `ssh server2 'sudo journalctl -u clash-meta -f'`
|
|
||||||
|
|
||||||
## Advantages
|
|
||||||
|
|
||||||
✅ Works on **both Wi-Fi and cellular**
|
|
||||||
✅ **No Tailscale VPN needed** (can keep it off)
|
|
||||||
✅ Shadowrocket VPN mode works independently
|
|
||||||
✅ Simple setup
|
|
||||||
|
|
||||||
## Get Credentials
|
|
||||||
|
|
||||||
Run this command to get your proxy credentials:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ssh server2 'cat ~/.clash_credentials.txt'
|
|
||||||
```
|
|
||||||
|
|
||||||
Then use them in Shadowrocket when adding the proxy server.
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
**Can't connect?**
|
|
||||||
1. Check server2 is online: `ssh server2 'sudo systemctl status clash-meta'`
|
|
||||||
2. Verify credentials are correct
|
|
||||||
3. Try different port: 7890, 7891, or 7892
|
|
||||||
4. Check firewall: `ssh server2 'sudo ufw status'`
|
|
||||||
|
|
||||||
**Proxy slow?**
|
|
||||||
- Normal - traffic goes: iPhone → Internet → server2 → Internet
|
|
||||||
- Depends on server2's connection speed
|
|
||||||
|
|
||||||
## Change Credentials
|
|
||||||
|
|
||||||
If you want to change the password:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ssh server2 'openssl rand -base64 12'
|
|
||||||
```
|
|
||||||
|
|
||||||
Then update `~/.config/clash-meta/config.yaml` and restart Clash.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
# Simple Workaround: Use Tailscale (Easiest)
|
|
||||||
|
|
||||||
## Quick Solution
|
|
||||||
|
|
||||||
Since you already have Tailscale set up, the **simplest workaround** is:
|
|
||||||
|
|
||||||
### Option 1: Use Tailscale + Shadowrocket (Temporarily)
|
|
||||||
|
|
||||||
1. **On iPhone:**
|
|
||||||
- Enable **Tailscale VPN** (Settings → Tailscale → toggle ON)
|
|
||||||
- Open **Shadowrocket**
|
|
||||||
- Add server: `100.70.115.1:7890`
|
|
||||||
- **Username:** `proxy_user`
|
|
||||||
- **Password:** `Cs7yBx1Rh9oK`
|
|
||||||
- Enable Shadowrocket
|
|
||||||
|
|
||||||
**Problem:** iOS only allows one VPN, so you can't use both...
|
|
||||||
|
|
||||||
### Option 2: Use Tailscale Only (No Shadowrocket)
|
|
||||||
|
|
||||||
1. **On iPhone:**
|
|
||||||
- Enable **Tailscale VPN**
|
|
||||||
- Settings → Wi-Fi → ⓘ → HTTP Proxy → Manual
|
|
||||||
- **Server:** `100.70.115.1`
|
|
||||||
- **Port:** `7890`
|
|
||||||
- **Authentication:** Username/Password
|
|
||||||
- **Username:** `proxy_user`
|
|
||||||
- **Password:** `Cs7yBx1Rh9oK`
|
|
||||||
|
|
||||||
**Limitation:** Only works on Wi-Fi, not cellular (iOS limitation)
|
|
||||||
|
|
||||||
### Option 3: SSH Tunnel on Mac + Share with iPhone
|
|
||||||
|
|
||||||
**On your Mac:**
|
|
||||||
|
|
||||||
1. **Create SSH tunnel:**
|
|
||||||
```bash
|
|
||||||
ssh -L 7890:127.0.0.1:7890 -N server2
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Install a local proxy bridge** (like `cow` or `polipo`):
|
|
||||||
```bash
|
|
||||||
# Using polipo (if installed)
|
|
||||||
polipo proxyAddress=0.0.0.0 proxyPort=8080 parentProxy=127.0.0.1:7890
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **On iPhone (same Wi-Fi):**
|
|
||||||
- Settings → Wi-Fi → ⓘ → HTTP Proxy → Manual
|
|
||||||
- **Server:** `192.168.1.XXX` (your Mac's IP)
|
|
||||||
- **Port:** `8080`
|
|
||||||
|
|
||||||
### Option 4: Use WireGuard (You Already Have It!)
|
|
||||||
|
|
||||||
You have `wg0` interface on server2! Use WireGuard instead:
|
|
||||||
|
|
||||||
1. **On iPhone:** Install WireGuard app
|
|
||||||
2. **On server2:** Generate WireGuard config
|
|
||||||
3. **Connect via WireGuard** to access `100.70.115.1:7890`
|
|
||||||
|
|
||||||
This works because WireGuard creates a VPN, and you can use Shadowrocket's proxy chain feature.
|
|
||||||
|
|
||||||
## Recommended: Option 2 (Tailscale + System Proxy)
|
|
||||||
|
|
||||||
**Easiest and works now:**
|
|
||||||
|
|
||||||
1. Enable Tailscale VPN on iPhone
|
|
||||||
2. Configure system HTTP proxy:
|
|
||||||
- Server: `100.70.115.1`
|
|
||||||
- Port: `7890`
|
|
||||||
- Username: `proxy_user`
|
|
||||||
- Password: `Cs7yBx1Rh9oK`
|
|
||||||
3. Works on Wi-Fi (cellular won't work, but it's a temporary workaround)
|
|
||||||
|
|
||||||
## When You Get Console Access
|
|
||||||
|
|
||||||
Add Security List rules for ports 7890, 7891, 7892, 9090, then you can use Shadowrocket directly with public IP.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# SSH Tunnel Workaround for Proxy Access
|
|
||||||
# This creates an SSH tunnel to forward proxy traffic through SSH (port 22)
|
|
||||||
|
|
||||||
echo "=== SSH Tunnel Workaround for Clash Proxy ==="
|
|
||||||
echo ""
|
|
||||||
echo "Since Oracle Cloud Security List blocks proxy ports, we'll use SSH port forwarding"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Get server details
|
|
||||||
SERVER="server2"
|
|
||||||
PROXY_PORT="7890"
|
|
||||||
LOCAL_PORT="7890"
|
|
||||||
|
|
||||||
echo "Creating SSH tunnel..."
|
|
||||||
echo "Local port: $LOCAL_PORT -> Remote: $SERVER:$PROXY_PORT"
|
|
||||||
echo ""
|
|
||||||
echo "Run this command on your Mac:"
|
|
||||||
echo ""
|
|
||||||
echo "ssh -L $LOCAL_PORT:127.0.0.1:$PROXY_PORT -N $SERVER"
|
|
||||||
echo ""
|
|
||||||
echo "Or for background:"
|
|
||||||
echo "ssh -f -N -L $LOCAL_PORT:127.0.0.1:$PROXY_PORT $SERVER"
|
|
||||||
echo ""
|
|
||||||
echo "Then configure Shadowrocket to use:"
|
|
||||||
echo " Server: 127.0.0.1 (localhost)"
|
|
||||||
echo " Port: $LOCAL_PORT"
|
|
||||||
echo " Username: proxy_user"
|
|
||||||
echo " Password: Cs7yBx1Rh9oK"
|
|
||||||
echo ""
|
|
||||||
echo "Note: This only works when SSH tunnel is active on your Mac"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Sync projects to server2
|
|
||||||
# Usage: ./sync-to-server.sh [project_name]
|
|
||||||
|
|
||||||
SERVER="server2"
|
|
||||||
REMOTE_PATH="/home/$USER/repos"
|
|
||||||
LOCAL_PATH="/Users/jimmyg/repos"
|
|
||||||
|
|
||||||
# Colors for output
|
|
||||||
RED='\033[0;31m'
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
NC='\033[0m' # No Color
|
|
||||||
|
|
||||||
echo -e "${YELLOW}Starting sync to $SERVER...${NC}"
|
|
||||||
|
|
||||||
if [ -n "$1" ]; then
|
|
||||||
# Sync specific project
|
|
||||||
PROJECT="$1"
|
|
||||||
echo -e "${GREEN}Syncing project: $PROJECT${NC}"
|
|
||||||
rsync -avz --delete \
|
|
||||||
--exclude='.git/' \
|
|
||||||
--exclude='node_modules/' \
|
|
||||||
--exclude='__pycache__/' \
|
|
||||||
--exclude='*.pyc' \
|
|
||||||
--exclude='.DS_Store' \
|
|
||||||
--exclude='*.log' \
|
|
||||||
"$LOCAL_PATH/$PROJECT/" \
|
|
||||||
"$SERVER:$REMOTE_PATH/$PROJECT/"
|
|
||||||
else
|
|
||||||
# Sync all projects
|
|
||||||
echo -e "${GREEN}Syncing all projects${NC}"
|
|
||||||
rsync -avz --delete \
|
|
||||||
--exclude='.git/' \
|
|
||||||
--exclude='node_modules/' \
|
|
||||||
--exclude='__pycache__/' \
|
|
||||||
--exclude='*.pyc' \
|
|
||||||
--exclude='.DS_Store' \
|
|
||||||
--exclude='*.log' \
|
|
||||||
"$LOCAL_PATH/" \
|
|
||||||
"$SERVER:$REMOTE_PATH/"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo -e "${GREEN}Sync completed!${NC}"
|
|
||||||
@@ -1,149 +0,0 @@
|
|||||||
# Synology USB Copy Troubleshooting
|
|
||||||
|
|
||||||
## Issue
|
|
||||||
USB Copy shows "Unavailable" status with message:
|
|
||||||
**"No USB/SD storage mounted to the front port or storage used for another task"**
|
|
||||||
|
|
||||||
## Possible Causes
|
|
||||||
|
|
||||||
### 1. No USB Device Connected
|
|
||||||
- USB/SD card not plugged into the front USB port
|
|
||||||
- USB device not properly connected
|
|
||||||
- USB device not recognized by Synology
|
|
||||||
|
|
||||||
### 2. USB Device Already in Use
|
|
||||||
- USB device mounted for another purpose (file sharing, etc.)
|
|
||||||
- Another USB Copy task using the same device
|
|
||||||
- USB device mounted as a shared folder
|
|
||||||
|
|
||||||
### 3. USB Copy Task Configuration Issue
|
|
||||||
- Task configured but USB device not detected
|
|
||||||
- Wrong USB port selected in task settings
|
|
||||||
- USB device format not supported
|
|
||||||
|
|
||||||
## Solutions
|
|
||||||
|
|
||||||
### Solution 1: Check USB Device Connection
|
|
||||||
|
|
||||||
1. **Physically check:**
|
|
||||||
- Ensure USB device is plugged into the **front USB port** (not rear ports)
|
|
||||||
- Try unplugging and reconnecting
|
|
||||||
- Try a different USB device to test
|
|
||||||
|
|
||||||
2. **Check in DSM:**
|
|
||||||
- Control Panel → External Devices
|
|
||||||
- See if USB device appears in the list
|
|
||||||
- Check if it shows as "Mounted" or "Unmounted"
|
|
||||||
|
|
||||||
### Solution 2: Unmount USB Device from Other Uses
|
|
||||||
|
|
||||||
1. **Check if USB is mounted as shared folder:**
|
|
||||||
- Control Panel → Shared Folder
|
|
||||||
- Look for USB device name
|
|
||||||
- If found, unmount it first
|
|
||||||
|
|
||||||
2. **Check other USB Copy tasks:**
|
|
||||||
- USB Copy → Check all tasks
|
|
||||||
- See if another task is using the USB device
|
|
||||||
- Disable or delete conflicting tasks
|
|
||||||
|
|
||||||
3. **Unmount manually:**
|
|
||||||
- Control Panel → External Devices
|
|
||||||
- Select USB device → Unmount
|
|
||||||
- Then try USB Copy again
|
|
||||||
|
|
||||||
### Solution 3: Check USB Copy Task Settings
|
|
||||||
|
|
||||||
1. **Open USB Copy task:**
|
|
||||||
- USB Copy → Select "Copy Button" task
|
|
||||||
- Go to "Task Settings" tab
|
|
||||||
|
|
||||||
2. **Verify settings:**
|
|
||||||
- Source: Should be [USB] or specific USB device
|
|
||||||
- Destination: Should be valid path
|
|
||||||
- Make sure correct USB port is selected
|
|
||||||
|
|
||||||
3. **Check "Trigger Time" tab:**
|
|
||||||
- Ensure trigger is properly configured
|
|
||||||
- If using "Copy Button" trigger, ensure button is enabled
|
|
||||||
|
|
||||||
### Solution 4: Restart USB Copy Service
|
|
||||||
|
|
||||||
1. **Stop USB Copy:**
|
|
||||||
- Package Center → USB Copy → Stop
|
|
||||||
|
|
||||||
2. **Unmount all USB devices:**
|
|
||||||
- Control Panel → External Devices → Unmount all
|
|
||||||
|
|
||||||
3. **Restart USB Copy:**
|
|
||||||
- Package Center → USB Copy → Start
|
|
||||||
|
|
||||||
4. **Reconnect USB device:**
|
|
||||||
- Plug USB device into front port
|
|
||||||
- Wait for it to be recognized
|
|
||||||
- Try USB Copy again
|
|
||||||
|
|
||||||
### Solution 5: Check USB Device Format
|
|
||||||
|
|
||||||
- **Supported formats:** FAT32, NTFS, exFAT, HFS+, ext4
|
|
||||||
- **Not supported:** Some encrypted formats, certain proprietary formats
|
|
||||||
- Try formatting USB device to FAT32 or exFAT if needed
|
|
||||||
|
|
||||||
## Diagnostic Steps
|
|
||||||
|
|
||||||
1. **Check USB device recognition:**
|
|
||||||
```
|
|
||||||
SSH to NAS → Run: lsusb
|
|
||||||
Or check: Control Panel → External Devices
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Check mount status:**
|
|
||||||
```
|
|
||||||
SSH to NAS → Run: mount | grep usb
|
|
||||||
Or check: Control Panel → External Devices → Status
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Check USB Copy logs:**
|
|
||||||
- USB Copy → Settings → View logs
|
|
||||||
- Look for error messages
|
|
||||||
|
|
||||||
## Common Issues
|
|
||||||
|
|
||||||
### Issue: "Copy Button" Task Shows Unavailable
|
|
||||||
- **Cause:** USB device not detected or already mounted elsewhere
|
|
||||||
- **Fix:** Unmount USB device from other uses, then reconnect
|
|
||||||
|
|
||||||
### Issue: USB Device Not Detected
|
|
||||||
- **Cause:** Wrong port, unsupported format, or hardware issue
|
|
||||||
- **Fix:** Try front port, check format, try different USB device
|
|
||||||
|
|
||||||
### Issue: Task Configured But Won't Run
|
|
||||||
- **Cause:** USB device mounted as shared folder or used by another task
|
|
||||||
- **Fix:** Unmount from shared folders, disable other USB Copy tasks
|
|
||||||
|
|
||||||
## Quick Fix Checklist
|
|
||||||
|
|
||||||
- [ ] USB device plugged into **front USB port**
|
|
||||||
- [ ] USB device appears in Control Panel → External Devices
|
|
||||||
- [ ] USB device is **not** mounted as shared folder
|
|
||||||
- [ ] No other USB Copy tasks using the same device
|
|
||||||
- [ ] USB Copy service is running (Package Center)
|
|
||||||
- [ ] USB device format is supported (FAT32/exFAT/NTFS)
|
|
||||||
- [ ] Try unmounting and reconnecting USB device
|
|
||||||
|
|
||||||
## If Still Not Working
|
|
||||||
|
|
||||||
1. **Check Synology logs:**
|
|
||||||
- Control Panel → Log Center
|
|
||||||
- Look for USB-related errors
|
|
||||||
|
|
||||||
2. **Try different USB device:**
|
|
||||||
- Test if issue is device-specific
|
|
||||||
|
|
||||||
3. **Check Synology model compatibility:**
|
|
||||||
- Some older models have USB Copy limitations
|
|
||||||
- Check Synology documentation for your model
|
|
||||||
|
|
||||||
4. **Contact Synology Support:**
|
|
||||||
- If hardware issue suspected
|
|
||||||
- Provide model number and error details
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
# Test Proxy Connection
|
|
||||||
|
|
||||||
## ✅ Security List Rules Added!
|
|
||||||
|
|
||||||
Now let's test if it works.
|
|
||||||
|
|
||||||
## Step 1: Wait for Rules to Propagate
|
|
||||||
Wait 30-60 seconds for Oracle Cloud to apply the rules.
|
|
||||||
|
|
||||||
## Step 2: Test from Your Mac (Quick Test)
|
|
||||||
|
|
||||||
Run this command to test:
|
|
||||||
```bash
|
|
||||||
curl --proxy http://proxy_user:Cs7yBx1Rh9oK@158.101.140.85:7890 http://httpbin.org/ip
|
|
||||||
```
|
|
||||||
|
|
||||||
**Expected result:** Should show `{"origin":"158.101.140.85"}`
|
|
||||||
|
|
||||||
If it works, the firewall is open! ✅
|
|
||||||
|
|
||||||
## Step 3: Configure Shadowrocket on iPhone
|
|
||||||
|
|
||||||
1. **Open Shadowrocket**
|
|
||||||
2. **Add Server:**
|
|
||||||
- Tap **"+"** button
|
|
||||||
- Select **HTTP**
|
|
||||||
- **Address:** `158.101.140.85`
|
|
||||||
- **Port:** `7890` (or `7892` for Mixed)
|
|
||||||
- **Username:** `proxy_user`
|
|
||||||
- **Password:** `Cs7yBx1Rh9oK`
|
|
||||||
- **Remark:** `server2-proxy`
|
|
||||||
- Tap **Done**
|
|
||||||
|
|
||||||
3. **Enable Shadowrocket:**
|
|
||||||
- Select your proxy server
|
|
||||||
- Toggle switch **ON**
|
|
||||||
- VPN icon should appear
|
|
||||||
|
|
||||||
4. **Test:**
|
|
||||||
- Open Safari
|
|
||||||
- Visit: https://api.ipify.org
|
|
||||||
- Should show: `158.101.140.85` ✅
|
|
||||||
|
|
||||||
## Step 4: Test on Cellular
|
|
||||||
|
|
||||||
1. Turn OFF Wi-Fi (use cellular only)
|
|
||||||
2. Open Safari
|
|
||||||
3. Visit: https://api.ipify.org
|
|
||||||
4. Should show server2's IP ✅
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
**Still timing out?**
|
|
||||||
- Wait another 1-2 minutes (rules can take time to propagate)
|
|
||||||
- Check Security List rules are saved
|
|
||||||
- Verify ports: 7890, 7891, 7892, 9090
|
|
||||||
- Try different port: 7892 (Mixed port)
|
|
||||||
|
|
||||||
**Connection works but slow?**
|
|
||||||
- Normal - traffic goes: iPhone → Internet → server2 → Internet
|
|
||||||
- Depends on server2's connection speed
|
|
||||||
|
|
||||||
**Can't connect?**
|
|
||||||
- Check server2 is running: `ssh server2 'sudo systemctl status clash-meta'`
|
|
||||||
- Verify credentials are correct
|
|
||||||
- Check firewall: `ssh server2 'sudo ufw status | grep 7890'`
|
|
||||||
|
|
||||||
## Success Indicators
|
|
||||||
|
|
||||||
✅ Mac test shows server2's IP
|
|
||||||
✅ Shadowrocket connects without timeout
|
|
||||||
✅ Safari shows server2's IP when proxy is on
|
|
||||||
✅ Works on both Wi-Fi and cellular
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,207 +0,0 @@
|
|||||||
# Time Machine NAS Connection Troubleshooting
|
|
||||||
|
|
||||||
## Issue
|
|
||||||
Time Machine shows "Connecting to backup disk..." but never completes, even though:
|
|
||||||
- ✅ NAS is accessible from Finder
|
|
||||||
- ✅ User `zjgump` is in administrators group (has full permissions)
|
|
||||||
- ✅ Network connectivity is fine (ping works, SMB works in Finder)
|
|
||||||
|
|
||||||
## Root Cause Analysis
|
|
||||||
|
|
||||||
### Key Finding
|
|
||||||
**`zjgump` is in the administrators group** - This means:
|
|
||||||
- Explicit file permissions won't apply to SMB/file protocols
|
|
||||||
- Admin users have full access by default
|
|
||||||
- The "Permission denied" errors are NOT about file permissions
|
|
||||||
|
|
||||||
### Actual Issues
|
|
||||||
1. **Credential Cache Mismatch**: macOS has saved credentials for `DS224plus` (without .local) but Time Machine tries to use `DS224plus.local`
|
|
||||||
2. **Stale Mounts**: Manual mounts interfere with Time Machine's automatic mounting
|
|
||||||
3. **Time Machine Process Permissions**: Time Machine runs as a different user than your login user
|
|
||||||
|
|
||||||
## Solutions
|
|
||||||
|
|
||||||
### Solution 1: Clear Credentials and Let Time Machine Mount Itself (Recommended)
|
|
||||||
|
|
||||||
1. **Unmount all existing mounts:**
|
|
||||||
```bash
|
|
||||||
diskutil unmount "/Volumes/Time Machine Folder" 2>/dev/null
|
|
||||||
sudo umount -f /Volumes/.timemachine/* 2>/dev/null
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Clear saved credentials:**
|
|
||||||
- Open **Keychain Access**
|
|
||||||
- Search for `DS224plus`
|
|
||||||
- Delete ALL entries related to DS224plus
|
|
||||||
- Also search for `Time Machine` and delete related entries
|
|
||||||
|
|
||||||
3. **Remove Time Machine destination:**
|
|
||||||
- System Settings → General → Time Machine
|
|
||||||
- Remove the existing backup disk (click `-` button)
|
|
||||||
|
|
||||||
4. **Re-add Time Machine:**
|
|
||||||
- Click "Add Backup Disk..."
|
|
||||||
- Select "Time Machine Folder" on "DS224plus.local" (the one with `.local`)
|
|
||||||
- When prompted, enter `zjgump` credentials
|
|
||||||
- **Let Time Machine mount it itself** - don't mount it manually first
|
|
||||||
|
|
||||||
### Solution 2: Use a Dedicated Time Machine User (Best Practice)
|
|
||||||
|
|
||||||
Synology recommends using a **dedicated non-admin user** for Time Machine:
|
|
||||||
|
|
||||||
1. **On Synology DSM:**
|
|
||||||
- Control Panel → User & Group → Create
|
|
||||||
- Create user: `tm-backup` (or similar)
|
|
||||||
- **Do NOT add to administrators group**
|
|
||||||
- Set password
|
|
||||||
|
|
||||||
2. **Grant permissions:**
|
|
||||||
- Control Panel → Shared Folder → Time Machine Folder → Edit → Permissions
|
|
||||||
- Add `tm-backup` user with **Read/Write** permission
|
|
||||||
- Check "Apply to this folder, sub-folders and files"
|
|
||||||
|
|
||||||
3. **Configure Time Machine on NAS:**
|
|
||||||
- Control Panel → File Services → Time Machine
|
|
||||||
- Select "Time Machine Folder" as the shared folder
|
|
||||||
- Select `tm-backup` as the user (or leave blank for all users)
|
|
||||||
|
|
||||||
4. **On macOS:**
|
|
||||||
- Remove existing Time Machine destination
|
|
||||||
- Add Backup Disk → Select "Time Machine Folder – DS224plus.local"
|
|
||||||
- When prompted, use `tm-backup` credentials (not `zjgump`)
|
|
||||||
|
|
||||||
### Solution 3: Fix Credential Cache for Admin User
|
|
||||||
|
|
||||||
If you want to keep using `zjgump` (admin user):
|
|
||||||
|
|
||||||
1. **Clear all DS224plus credentials:**
|
|
||||||
```bash
|
|
||||||
security delete-internet-password -s "DS224plus" 2>/dev/null
|
|
||||||
security delete-internet-password -s "DS224plus.local" 2>/dev/null
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Remove Time Machine destination**
|
|
||||||
|
|
||||||
3. **Manually connect via Finder first:**
|
|
||||||
- Finder → ⌘K → `smb://DS224plus.local`
|
|
||||||
- Connect as `zjgump`
|
|
||||||
- This will save the credential properly
|
|
||||||
|
|
||||||
4. **Then add Time Machine:**
|
|
||||||
- System Settings → Time Machine → Add Backup Disk
|
|
||||||
- Select "Time Machine Folder – DS224plus.local"
|
|
||||||
- It should use the saved credential
|
|
||||||
|
|
||||||
### Solution 4: Use IP Address Instead of Hostname
|
|
||||||
|
|
||||||
If Bonjour (.local) is causing issues:
|
|
||||||
|
|
||||||
1. **Find NAS IP:**
|
|
||||||
```bash
|
|
||||||
ping -c 1 DS224plus.local | grep PING
|
|
||||||
# Or check your router's DHCP table
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Connect via IP:**
|
|
||||||
- System Settings → Time Machine → Add Backup Disk
|
|
||||||
- If it doesn't show up, manually mount first:
|
|
||||||
- Finder → ⌘K → `smb://192.168.1.172/Time Machine Folder`
|
|
||||||
- Connect as `zjgump`
|
|
||||||
- Then add the mounted share in Time Machine
|
|
||||||
|
|
||||||
## Diagnostic Commands
|
|
||||||
|
|
||||||
### Check Current Mounts
|
|
||||||
```bash
|
|
||||||
mount | grep -i "timemachine\|ds224plus"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Check Time Machine Logs
|
|
||||||
```bash
|
|
||||||
log show --predicate 'subsystem == "com.apple.TimeMachine"' --last 10m --info | tail -50
|
|
||||||
```
|
|
||||||
|
|
||||||
### Check Saved Credentials
|
|
||||||
```bash
|
|
||||||
security find-internet-password -s "DS224plus"
|
|
||||||
security find-internet-password -s "DS224plus.local"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Test SMB Connection
|
|
||||||
```bash
|
|
||||||
smbutil status DS224plus.local
|
|
||||||
```
|
|
||||||
|
|
||||||
### Check Time Machine Configuration
|
|
||||||
```bash
|
|
||||||
tmutil listbackups
|
|
||||||
defaults read /Library/Preferences/com.apple.TimeMachine
|
|
||||||
```
|
|
||||||
|
|
||||||
## Common Errors and Fixes
|
|
||||||
|
|
||||||
### "Time Machine could not back up the disk because it is nearly full"
|
|
||||||
- **Cause**: The **source disk** (Macintosh HD) is nearly full, NOT the destination (NAS)
|
|
||||||
- **Symptoms**: Error says disk is "nearly full" but NAS shows plenty of space (e.g., 1.67TB available)
|
|
||||||
- **Fix**: Free up space on your Mac's internal disk:
|
|
||||||
1. Run the diagnostic script: `./free_disk_space.sh`
|
|
||||||
2. Run the cleanup script: `./fix_time_machine_disk_full.sh`
|
|
||||||
3. Or manually:
|
|
||||||
- Empty Trash: `rm -rf ~/.Trash/*`
|
|
||||||
- Clean caches: `rm -rf ~/Library/Caches/*`
|
|
||||||
- Review Downloads folder (often has large files)
|
|
||||||
- Use macOS Storage Management: Apple Menu → About This Mac → Storage → Manage
|
|
||||||
- **Why**: Time Machine needs free space on the source disk to:
|
|
||||||
- Create local snapshots
|
|
||||||
- Stage files for backup
|
|
||||||
- Maintain the backup process
|
|
||||||
- **Minimum**: Aim for at least 5-10GB free space for Time Machine to work properly
|
|
||||||
|
|
||||||
### "Deleted files but space not freed" / "Stuck Time Machine snapshot"
|
|
||||||
- **Cause**: APFS snapshots (especially Time Machine local snapshots) hold onto deleted file space
|
|
||||||
- **Symptoms**:
|
|
||||||
- Deleted 20GB+ of files but disk space didn't increase
|
|
||||||
- Error: "Stale NFS file handle" when trying to delete snapshots
|
|
||||||
- `tmutil listlocalsnapshots /` shows snapshots that can't be deleted
|
|
||||||
- **Fix**:
|
|
||||||
1. **Quick fix - Restart Mac**: Often the simplest solution - snapshots are released after restart
|
|
||||||
2. **Remove Time Machine destination temporarily**:
|
|
||||||
- System Settings → Time Machine → Remove backup disk
|
|
||||||
- Delete snapshot: `sudo tmutil deletelocalsnapshots <date>`
|
|
||||||
- Re-add Time Machine destination
|
|
||||||
3. **Use the fix script**: `./fix_stuck_snapshot.sh` (guides you through the process)
|
|
||||||
4. **Force purge**: `sudo purge` (if available)
|
|
||||||
- **Why**: Time Machine creates local snapshots before backing up. If the backup destination (NAS) is unreachable or has a stale connection, the snapshot gets stuck and holds onto space from deleted files.
|
|
||||||
- **Prevention**: Ensure Time Machine can reliably connect to backup destination
|
|
||||||
|
|
||||||
### "Permission denied" on mount point
|
|
||||||
- **Cause**: Manual mount with wrong permissions
|
|
||||||
- **Fix**: Unmount and let Time Machine mount it itself
|
|
||||||
|
|
||||||
### "Connecting to backup disk..." hangs
|
|
||||||
- **Cause**: Credential cache mismatch or stale mount
|
|
||||||
- **Fix**: Clear credentials, unmount all, re-add
|
|
||||||
|
|
||||||
### "Server may not exist or unavailable"
|
|
||||||
- **Cause**: Using wrong hostname (DS224plus vs DS224plus.local)
|
|
||||||
- **Fix**: Always use `.local` version or IP address
|
|
||||||
|
|
||||||
## Prevention
|
|
||||||
|
|
||||||
1. **Don't manually mount Time Machine shares** - let Time Machine do it
|
|
||||||
2. **Use dedicated non-admin user** for Time Machine (best practice)
|
|
||||||
3. **Keep credentials in sync** - if you change NAS password, update on Mac
|
|
||||||
4. **Use `.local` hostname** - more reliable than IP or NetBIOS name
|
|
||||||
|
|
||||||
## Notes
|
|
||||||
|
|
||||||
- Admin users (`zjgump`) bypass file-level permissions on Synology
|
|
||||||
- Time Machine runs as `_backup` user on macOS, not your login user
|
|
||||||
- Bonjour (`.local`) is preferred over NetBIOS for Time Machine
|
|
||||||
- Manual mounts can interfere with Time Machine's automatic mounting
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
# Troubleshooting Proxy Connection Timeout
|
|
||||||
|
|
||||||
## Issue
|
|
||||||
Connection test timeout when connecting to proxy from iPhone/Shadowrocket.
|
|
||||||
|
|
||||||
## Status Check
|
|
||||||
✅ Clash is running
|
|
||||||
✅ Listening on ports 7890, 7891, 7892
|
|
||||||
✅ Local connection works (tested from server2)
|
|
||||||
✅ Authentication configured
|
|
||||||
✅ UFW firewall allows ports
|
|
||||||
|
|
||||||
## Possible Causes
|
|
||||||
|
|
||||||
### 1. Oracle Cloud Security List / Firewall
|
|
||||||
Oracle Cloud has a **Security List** that acts as a firewall. Even if UFW allows the ports, Oracle's firewall might be blocking them.
|
|
||||||
|
|
||||||
**Solution:** Check Oracle Cloud Console:
|
|
||||||
1. Go to Oracle Cloud Console
|
|
||||||
2. Networking → Virtual Cloud Networks
|
|
||||||
3. Find your VCN
|
|
||||||
4. Security Lists → Ingress Rules
|
|
||||||
5. Add rules for ports 7890, 7891, 7892, 9090
|
|
||||||
- Source: 0.0.0.0/0 (or your IP for security)
|
|
||||||
- Protocol: TCP
|
|
||||||
- Port: 7890, 7891, 7892, 9090
|
|
||||||
|
|
||||||
### 2. Network ACL
|
|
||||||
Oracle Cloud also has Network ACLs that might block traffic.
|
|
||||||
|
|
||||||
### 3. IPv6 vs IPv4
|
|
||||||
Clash shows as `tcp6` but `*:7890` means it listens on both IPv4 and IPv6. This should be fine.
|
|
||||||
|
|
||||||
### 4. Connection from iPhone
|
|
||||||
Test from a different network to see if it's network-specific.
|
|
||||||
|
|
||||||
## Quick Tests
|
|
||||||
|
|
||||||
### Test 1: Check if port is reachable
|
|
||||||
```bash
|
|
||||||
# From your Mac (not iPhone)
|
|
||||||
nc -zv 158.101.140.85 7890
|
|
||||||
# or
|
|
||||||
telnet 158.101.140.85 7890
|
|
||||||
```
|
|
||||||
|
|
||||||
### Test 2: Test from server2 itself
|
|
||||||
```bash
|
|
||||||
ssh server2 'curl -v --proxy http://proxy_user:Cs7yBx1Rh9oK@127.0.0.1:7890 http://httpbin.org/ip'
|
|
||||||
```
|
|
||||||
|
|
||||||
### Test 3: Check Oracle Cloud Security List
|
|
||||||
- Log into Oracle Cloud Console
|
|
||||||
- Check Security List rules for your instance
|
|
||||||
|
|
||||||
## Most Likely Issue: Oracle Cloud Security List
|
|
||||||
|
|
||||||
Oracle Cloud blocks all incoming traffic by default unless explicitly allowed in the Security List. UFW on the server won't help if Oracle's firewall blocks it first.
|
|
||||||
|
|
||||||
## Solution Steps
|
|
||||||
|
|
||||||
1. **Check Oracle Cloud Console:**
|
|
||||||
- Go to your instance
|
|
||||||
- Click on the VCN/subnet
|
|
||||||
- Security Lists → Ingress Rules
|
|
||||||
- Add rules for ports 7890, 7891, 7892
|
|
||||||
|
|
||||||
2. **Or use Oracle Cloud CLI:**
|
|
||||||
```bash
|
|
||||||
# Add security list rule (example - adjust for your setup)
|
|
||||||
oci network security-list update --security-list-id <your-security-list-id> ...
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Test again from iPhone after adding rules**
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Use External Drive to Free Space for Update
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "=== Use External Drive for Update ==="
|
|
||||||
echo ""
|
|
||||||
echo "External drive detected! This is your solution."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Find external drive
|
|
||||||
EXTERNAL_VOLUMES=$(ls -d /Volumes/* 2>/dev/null | grep -v -E "Macintosh|Preboot|Recovery|VM|Download" || echo "")
|
|
||||||
|
|
||||||
if [ -z "$EXTERNAL_VOLUMES" ]; then
|
|
||||||
echo "⚠️ No external volumes found mounted"
|
|
||||||
echo ""
|
|
||||||
echo "Please:"
|
|
||||||
echo " 1. Connect your external USB drive"
|
|
||||||
echo " 2. Wait for it to mount"
|
|
||||||
echo " 3. Run this script again"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Found external volume(s):"
|
|
||||||
echo "$EXTERNAL_VOLUMES" | while read vol; do
|
|
||||||
SIZE=$(df -h "$vol" 2>/dev/null | tail -1 | awk '{print $2}')
|
|
||||||
FREE=$(df -h "$vol" 2>/dev/null | tail -1 | awk '{print $4}')
|
|
||||||
echo " - $vol ($SIZE total, $FREE free)"
|
|
||||||
done
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Use first external volume
|
|
||||||
EXTERNAL_VOL=$(echo "$EXTERNAL_VOLUMES" | head -1)
|
|
||||||
echo "Using: $EXTERNAL_VOL"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
FREE_SPACE=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
FREE_SPACE_GB=$(echo "scale=2; $FREE_SPACE / 1024 / 1024" | bc)
|
|
||||||
echo "Current Mac free space: ${FREE_SPACE_GB}GB"
|
|
||||||
echo "Need: 17.64GB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "📦 Large files you can move to external drive:"
|
|
||||||
echo ""
|
|
||||||
echo " Downloads: 8.7GB"
|
|
||||||
echo " .ollama: 17GB"
|
|
||||||
echo " .local: 18GB"
|
|
||||||
echo " Total: ~44GB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "🔧 Steps:"
|
|
||||||
echo ""
|
|
||||||
echo "1. Move large files to external drive:"
|
|
||||||
echo " mv ~/Downloads \"$EXTERNAL_VOL/Downloads_backup\""
|
|
||||||
echo " mv ~/.ollama \"$EXTERNAL_VOL/ollama_backup\""
|
|
||||||
echo " mv ~/.local \"$EXTERNAL_VOL/local_backup\""
|
|
||||||
echo ""
|
|
||||||
echo "2. This should free ~44GB on Mac"
|
|
||||||
echo ""
|
|
||||||
echo "3. Install macOS update"
|
|
||||||
echo ""
|
|
||||||
echo "4. After update clears snapshot, move files back"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
read -p "Move Downloads, .ollama, and .local to external drive? (y/n) " -n 1 -r
|
|
||||||
echo ""
|
|
||||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
||||||
echo ""
|
|
||||||
echo "Moving files..."
|
|
||||||
|
|
||||||
# Move Downloads
|
|
||||||
if [ -d ~/Downloads ]; then
|
|
||||||
echo "Moving Downloads (8.7GB)..."
|
|
||||||
mv ~/Downloads "$EXTERNAL_VOL/Downloads_backup" && \
|
|
||||||
echo " ✅ Moved Downloads" || \
|
|
||||||
echo " ⚠️ Error moving Downloads"
|
|
||||||
mkdir ~/Downloads
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Move .ollama
|
|
||||||
if [ -d ~/.ollama ]; then
|
|
||||||
echo "Moving .ollama (17GB)..."
|
|
||||||
mv ~/.ollama "$EXTERNAL_VOL/ollama_backup" && \
|
|
||||||
echo " ✅ Moved .ollama" || \
|
|
||||||
echo " ⚠️ Error moving .ollama"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Move .local
|
|
||||||
if [ -d ~/.local ]; then
|
|
||||||
echo "Moving .local (18GB)..."
|
|
||||||
mv ~/.local "$EXTERNAL_VOL/local_backup" && \
|
|
||||||
echo " ✅ Moved .local" || \
|
|
||||||
echo " ⚠️ Error moving .local"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "⏳ Waiting for space to update..."
|
|
||||||
sleep 5
|
|
||||||
|
|
||||||
NEW_FREE=$(df / | tail -1 | awk '{print $4}')
|
|
||||||
NEW_FREE_GB=$(echo "scale=2; $NEW_FREE / 1024 / 1024" | bc)
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "New free space: ${NEW_FREE_GB}GB"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
if (( $(echo "$NEW_FREE_GB > 17" | bc -l) )); then
|
|
||||||
echo "✅ Enough space! Now install update:"
|
|
||||||
echo " System Settings → General → Software Update"
|
|
||||||
echo " OR"
|
|
||||||
echo " sudo softwareupdate --download --all"
|
|
||||||
else
|
|
||||||
echo "⚠️ Still not enough. May need to move more files."
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "Cancelled."
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
# NAS WebDAV External Access Troubleshooting
|
|
||||||
|
|
||||||
This repository contains diagnostic tools and guides to help troubleshoot WebDAV external access issues on NAS systems.
|
|
||||||
|
|
||||||
## Problem
|
|
||||||
|
|
||||||
WebDAV works on intranet but fails from external networks with "Connection refused" error.
|
|
||||||
|
|
||||||
## Quick Start
|
|
||||||
|
|
||||||
1. **Run the diagnostic script on your NAS:**
|
|
||||||
```bash
|
|
||||||
sudo ./diagnose_webdav.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Check port forwarding:**
|
|
||||||
```bash
|
|
||||||
./check_port_forwarding.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Review the troubleshooting guide:**
|
|
||||||
- See [TROUBLESHOOTING.md](TROUBLESHOOTING.md) for detailed solutions
|
|
||||||
|
|
||||||
## Files
|
|
||||||
|
|
||||||
- `diagnose_webdav.sh` - Comprehensive diagnostic script to check service binding, firewall, and configuration
|
|
||||||
- `check_port_forwarding.sh` - Tests port accessibility and provides port forwarding checklist
|
|
||||||
- `TROUBLESHOOTING.md` - Detailed troubleshooting guide with common issues and solutions
|
|
||||||
|
|
||||||
## Most Common Issues
|
|
||||||
|
|
||||||
1. **Service bound to localhost only** - Service listens on `127.0.0.1:5006` instead of `0.0.0.0:5006`
|
|
||||||
2. **Firewall blocking port** - Port 5006 not allowed in firewall rules
|
|
||||||
3. **Router port forwarding not configured** - External port 5006 not forwarded to NAS internal IP
|
|
||||||
4. **Router firewall blocking** - Router firewall blocking incoming connections
|
|
||||||
|
|
||||||
## Quick Fix
|
|
||||||
|
|
||||||
The most common fix is ensuring your WebDAV service is bound to all interfaces:
|
|
||||||
|
|
||||||
**Apache:**
|
|
||||||
```apache
|
|
||||||
Listen 0.0.0.0:5006
|
|
||||||
```
|
|
||||||
|
|
||||||
**Nginx:**
|
|
||||||
```nginx
|
|
||||||
listen 0.0.0.0:5006;
|
|
||||||
```
|
|
||||||
|
|
||||||
Then configure router port forwarding: External 5006 → Internal NAS IP:5006
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
All scripts should be run on your NAS system:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Make scripts executable (already done)
|
|
||||||
chmod +x *.sh
|
|
||||||
|
|
||||||
# Run diagnostics
|
|
||||||
sudo ./diagnose_webdav.sh
|
|
||||||
|
|
||||||
# Check port forwarding
|
|
||||||
./check_port_forwarding.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
@@ -1,164 +0,0 @@
|
|||||||
# WebDAV External Access Troubleshooting Guide
|
|
||||||
|
|
||||||
## Problem
|
|
||||||
WebDAV works on intranet but fails from external networks with "Connection refused" error.
|
|
||||||
|
|
||||||
## Common Causes and Solutions
|
|
||||||
|
|
||||||
### 1. Service Bound to Localhost Only
|
|
||||||
|
|
||||||
**Symptom:** Service only listens on `127.0.0.1` or `::1` instead of all interfaces.
|
|
||||||
|
|
||||||
**Solution:**
|
|
||||||
- **Apache:** Change `Listen 127.0.0.1:5006` to `Listen 0.0.0.0:5006` or `Listen *:5006`
|
|
||||||
- **Nginx:** Change `listen 127.0.0.1:5006;` to `listen 0.0.0.0:5006;` or `listen *:5006;`
|
|
||||||
- **Other services:** Ensure binding to `0.0.0.0` or `*` instead of `localhost`/`127.0.0.1`
|
|
||||||
|
|
||||||
**Check:**
|
|
||||||
```bash
|
|
||||||
netstat -tuln | grep 5006
|
|
||||||
# or
|
|
||||||
ss -tuln | grep 5006
|
|
||||||
```
|
|
||||||
|
|
||||||
If you see `127.0.0.1:5006` or `::1:5006`, the service is only accessible locally.
|
|
||||||
|
|
||||||
### 2. Firewall Blocking Port 5006
|
|
||||||
|
|
||||||
**Solution:**
|
|
||||||
|
|
||||||
**UFW (Ubuntu/Debian):**
|
|
||||||
```bash
|
|
||||||
sudo ufw allow 5006/tcp
|
|
||||||
sudo ufw reload
|
|
||||||
```
|
|
||||||
|
|
||||||
**firewalld (CentOS/RHEL):**
|
|
||||||
```bash
|
|
||||||
sudo firewall-cmd --permanent --add-port=5006/tcp
|
|
||||||
sudo firewall-cmd --reload
|
|
||||||
```
|
|
||||||
|
|
||||||
**iptables:**
|
|
||||||
```bash
|
|
||||||
sudo iptables -A INPUT -p tcp --dport 5006 -j ACCEPT
|
|
||||||
sudo iptables-save
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Router Port Forwarding Not Configured
|
|
||||||
|
|
||||||
**Solution:**
|
|
||||||
1. Access your router's admin panel
|
|
||||||
2. Navigate to Port Forwarding / Virtual Server settings
|
|
||||||
3. Add rule:
|
|
||||||
- **External Port:** 5006
|
|
||||||
- **Internal IP:** Your NAS IP address (e.g., 192.168.1.100)
|
|
||||||
- **Internal Port:** 5006
|
|
||||||
- **Protocol:** TCP
|
|
||||||
4. Save and apply changes
|
|
||||||
|
|
||||||
### 4. Router Firewall Blocking Incoming Connections
|
|
||||||
|
|
||||||
**Solution:**
|
|
||||||
- Check router firewall settings
|
|
||||||
- Ensure port 5006 is allowed for incoming connections
|
|
||||||
- Some routers have separate WAN firewall rules
|
|
||||||
|
|
||||||
### 5. ISP Blocking Port 5006
|
|
||||||
|
|
||||||
**Solution:**
|
|
||||||
- Some ISPs block certain ports
|
|
||||||
- Try a different external port (e.g., 5007, 8080)
|
|
||||||
- Update port forwarding to use the new port
|
|
||||||
|
|
||||||
### 6. Service Not Running or Crashed
|
|
||||||
|
|
||||||
**Check service status:**
|
|
||||||
```bash
|
|
||||||
# For systemd services
|
|
||||||
systemctl status webdav
|
|
||||||
# or
|
|
||||||
systemctl status apache2
|
|
||||||
# or
|
|
||||||
systemctl status nginx
|
|
||||||
|
|
||||||
# Check if process is running
|
|
||||||
ps aux | grep -i webdav
|
|
||||||
```
|
|
||||||
|
|
||||||
**Restart service:**
|
|
||||||
```bash
|
|
||||||
sudo systemctl restart webdav
|
|
||||||
# or
|
|
||||||
sudo systemctl restart apache2
|
|
||||||
# or
|
|
||||||
sudo systemctl restart nginx
|
|
||||||
```
|
|
||||||
|
|
||||||
### 7. NAS-Specific Configuration
|
|
||||||
|
|
||||||
**Synology NAS:**
|
|
||||||
1. Control Panel → External Access → Router Configuration
|
|
||||||
2. Enable port forwarding for port 5006
|
|
||||||
3. Control Panel → Security → Firewall
|
|
||||||
4. Ensure port 5006 is allowed
|
|
||||||
|
|
||||||
**QNAP NAS:**
|
|
||||||
1. Network & Virtual Switch → Port Forwarding
|
|
||||||
2. Add rule for port 5006
|
|
||||||
3. Security → Firewall → Allow port 5006
|
|
||||||
|
|
||||||
**Other NAS:**
|
|
||||||
- Check NAS admin panel for port forwarding/firewall settings
|
|
||||||
- Ensure WebDAV service is enabled and configured for external access
|
|
||||||
|
|
||||||
## Diagnostic Steps
|
|
||||||
|
|
||||||
1. **Run the diagnostic script:**
|
|
||||||
```bash
|
|
||||||
chmod +x diagnose_webdav.sh
|
|
||||||
sudo ./diagnose_webdav.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Test local connection:**
|
|
||||||
```bash
|
|
||||||
curl -k -X PROPFIND https://localhost:5006
|
|
||||||
# or
|
|
||||||
curl -k -X PROPFIND https://127.0.0.1:5006
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Test from internal network:**
|
|
||||||
```bash
|
|
||||||
curl -k -X PROPFIND https://<NAS_INTERNAL_IP>:5006
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **Test from external network:**
|
|
||||||
```bash
|
|
||||||
curl -k -X PROPFIND https://jimmygan.myds.me:5006
|
|
||||||
```
|
|
||||||
|
|
||||||
5. **Check if port is reachable externally:**
|
|
||||||
```bash
|
|
||||||
# From external network
|
|
||||||
telnet jimmygan.myds.me 5006
|
|
||||||
# or
|
|
||||||
nc -zv jimmygan.myds.me 5006
|
|
||||||
```
|
|
||||||
|
|
||||||
## Quick Fix Checklist
|
|
||||||
|
|
||||||
- [ ] Service is bound to `0.0.0.0:5006` (not `127.0.0.1:5006`)
|
|
||||||
- [ ] Firewall allows port 5006
|
|
||||||
- [ ] Router port forwarding configured (External 5006 → Internal NAS IP:5006)
|
|
||||||
- [ ] Router firewall allows incoming connections on port 5006
|
|
||||||
- [ ] WebDAV service is running
|
|
||||||
- [ ] Tested local connection (works)
|
|
||||||
- [ ] Tested internal network connection (works)
|
|
||||||
- [ ] External connection still fails → Check ISP/port blocking
|
|
||||||
|
|
||||||
## Additional Notes
|
|
||||||
|
|
||||||
- **DDNS:** Your domain `jimmygan.myds.me` appears to be a DDNS service. Ensure it's properly configured and pointing to your current external IP.
|
|
||||||
- **HTTPS:** Since you're using HTTPS, ensure SSL certificate is valid and the service is configured for SSL/TLS.
|
|
||||||
- **IPv6:** The error shows IPv6 connection attempts. If your router/NAS doesn't support IPv6 properly, you may need to disable IPv6 or configure it separately.
|
|
||||||
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Port Forwarding Test Script
|
|
||||||
# Tests if port 5006 is accessible from external networks
|
|
||||||
|
|
||||||
echo "=========================================="
|
|
||||||
echo "Port Forwarding Test for WebDAV (Port 5006)"
|
|
||||||
echo "=========================================="
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Get external IP
|
|
||||||
echo "1. Checking external IP address..."
|
|
||||||
EXTERNAL_IP=$(curl -s ifconfig.me 2>/dev/null || curl -s icanhazip.com 2>/dev/null)
|
|
||||||
if [ -z "$EXTERNAL_IP" ]; then
|
|
||||||
echo "❌ Unable to determine external IP"
|
|
||||||
else
|
|
||||||
echo "✅ External IP: $EXTERNAL_IP"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Get internal IP
|
|
||||||
echo "2. Checking internal IP address..."
|
|
||||||
if command -v ip &> /dev/null; then
|
|
||||||
INTERNAL_IP=$(ip route get 8.8.8.8 2>/dev/null | grep -oP 'src \K\S+' | head -1)
|
|
||||||
elif command -v hostname &> /dev/null; then
|
|
||||||
INTERNAL_IP=$(hostname -I | awk '{print $1}')
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$INTERNAL_IP" ]; then
|
|
||||||
echo "⚠️ Unable to determine internal IP"
|
|
||||||
else
|
|
||||||
echo "✅ Internal IP: $INTERNAL_IP"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Test local port
|
|
||||||
echo "3. Testing local port 5006..."
|
|
||||||
if command -v nc &> /dev/null; then
|
|
||||||
if timeout 2 nc -zv localhost 5006 2>&1 | grep -q "succeeded"; then
|
|
||||||
echo "✅ Port 5006 is open locally"
|
|
||||||
else
|
|
||||||
echo "❌ Port 5006 is NOT open locally"
|
|
||||||
echo " → Service may not be running or bound incorrectly"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "⚠️ netcat not available, skipping local test"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Test internal network port
|
|
||||||
if [ -n "$INTERNAL_IP" ]; then
|
|
||||||
echo "4. Testing internal network access..."
|
|
||||||
if command -v nc &> /dev/null; then
|
|
||||||
if timeout 2 nc -zv "$INTERNAL_IP" 5006 2>&1 | grep -q "succeeded"; then
|
|
||||||
echo "✅ Port 5006 accessible from internal network"
|
|
||||||
else
|
|
||||||
echo "❌ Port 5006 NOT accessible from internal network"
|
|
||||||
echo " → Service may be bound to localhost only"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Test external port (if external IP service available)
|
|
||||||
echo "5. Testing external port accessibility..."
|
|
||||||
echo " (This requires an external service - may not work in all environments)"
|
|
||||||
if command -v nc &> /dev/null && [ -n "$EXTERNAL_IP" ]; then
|
|
||||||
echo " Attempting to test from external perspective..."
|
|
||||||
echo " Note: This test may not work if your network blocks outbound connections"
|
|
||||||
echo ""
|
|
||||||
echo " Manual test recommended:"
|
|
||||||
echo " From a device outside your network, run:"
|
|
||||||
echo " telnet $EXTERNAL_IP 5006"
|
|
||||||
echo " or"
|
|
||||||
echo " nc -zv $EXTERNAL_IP 5006"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Port forwarding checklist
|
|
||||||
echo "6. Port Forwarding Configuration Checklist"
|
|
||||||
echo "-------------------------------------------"
|
|
||||||
echo "On your router, ensure:"
|
|
||||||
echo ""
|
|
||||||
echo " External Port: 5006"
|
|
||||||
echo " Internal IP: $INTERNAL_IP (your NAS IP)"
|
|
||||||
echo " Internal Port: 5006"
|
|
||||||
echo " Protocol: TCP"
|
|
||||||
echo ""
|
|
||||||
echo " Status: [ ] Configured"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Firewall checklist
|
|
||||||
echo "7. Firewall Configuration Checklist"
|
|
||||||
echo "-------------------------------------------"
|
|
||||||
echo "On your NAS/router:"
|
|
||||||
echo " [ ] Port 5006 allowed in firewall"
|
|
||||||
echo " [ ] Incoming connections on port 5006 allowed"
|
|
||||||
echo " [ ] Service bound to 0.0.0.0:5006 (not 127.0.0.1:5006)"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "=========================================="
|
|
||||||
echo "Next Steps"
|
|
||||||
echo "=========================================="
|
|
||||||
echo ""
|
|
||||||
echo "If local test fails:"
|
|
||||||
echo " 1. Check if WebDAV service is running"
|
|
||||||
echo " 2. Check service configuration (Listen directive)"
|
|
||||||
echo ""
|
|
||||||
echo "If local test passes but internal fails:"
|
|
||||||
echo " 1. Service is likely bound to localhost only"
|
|
||||||
echo " 2. Change Listen/ServerName to 0.0.0.0:5006"
|
|
||||||
echo ""
|
|
||||||
echo "If internal test passes but external fails:"
|
|
||||||
echo " 1. Check router port forwarding configuration"
|
|
||||||
echo " 2. Check router firewall settings"
|
|
||||||
echo " 3. Verify ISP is not blocking port 5006"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
@@ -1,142 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# WebDAV External Access Diagnostic Script
|
|
||||||
# This script helps diagnose why WebDAV is not accessible from external networks
|
|
||||||
|
|
||||||
echo "=========================================="
|
|
||||||
echo "WebDAV External Access Diagnostic Tool"
|
|
||||||
echo "=========================================="
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check if running as root (needed for some checks)
|
|
||||||
if [ "$EUID" -ne 0 ]; then
|
|
||||||
echo "⚠️ Some checks may require root privileges"
|
|
||||||
echo ""
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 1. Check what's listening on port 5006
|
|
||||||
echo "1. Checking what's listening on port 5006..."
|
|
||||||
echo "-------------------------------------------"
|
|
||||||
if command -v netstat &> /dev/null; then
|
|
||||||
echo "Using netstat:"
|
|
||||||
netstat -tuln | grep 5006 || echo "❌ Nothing found listening on port 5006"
|
|
||||||
elif command -v ss &> /dev/null; then
|
|
||||||
echo "Using ss:"
|
|
||||||
ss -tuln | grep 5006 || echo "❌ Nothing found listening on port 5006"
|
|
||||||
else
|
|
||||||
echo "⚠️ netstat or ss not available"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 2. Check if service is bound to localhost only
|
|
||||||
echo "2. Checking if service is bound to localhost only..."
|
|
||||||
echo "-------------------------------------------"
|
|
||||||
if command -v netstat &> /dev/null; then
|
|
||||||
netstat -tuln | grep 5006 | grep "127.0.0.1\|::1" && echo "❌ Service is bound to localhost only!" || echo "✅ Service is not bound to localhost only"
|
|
||||||
elif command -v ss &> /dev/null; then
|
|
||||||
ss -tuln | grep 5006 | grep "127.0.0.1\|::1" && echo "❌ Service is bound to localhost only!" || echo "✅ Service is not bound to localhost only"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 3. Check if port 5006 is open in firewall
|
|
||||||
echo "3. Checking firewall status..."
|
|
||||||
echo "-------------------------------------------"
|
|
||||||
if command -v ufw &> /dev/null; then
|
|
||||||
echo "UFW Status:"
|
|
||||||
ufw status | grep 5006 || echo "⚠️ Port 5006 not found in UFW rules"
|
|
||||||
elif command -v firewall-cmd &> /dev/null; then
|
|
||||||
echo "firewalld Status:"
|
|
||||||
firewall-cmd --list-ports | grep 5006 || echo "⚠️ Port 5006 not found in firewalld rules"
|
|
||||||
elif command -v iptables &> /dev/null; then
|
|
||||||
echo "iptables rules for port 5006:"
|
|
||||||
iptables -L -n | grep 5006 || echo "⚠️ No iptables rules found for port 5006"
|
|
||||||
else
|
|
||||||
echo "⚠️ No common firewall tool detected"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 4. Check WebDAV service status (common services)
|
|
||||||
echo "4. Checking WebDAV service status..."
|
|
||||||
echo "-------------------------------------------"
|
|
||||||
if systemctl list-units --type=service | grep -i webdav &> /dev/null; then
|
|
||||||
systemctl list-units --type=service | grep -i webdav | while read service; do
|
|
||||||
servicename=$(echo $service | awk '{print $1}')
|
|
||||||
echo "Service: $servicename"
|
|
||||||
systemctl status $servicename --no-pager | head -5
|
|
||||||
done
|
|
||||||
else
|
|
||||||
echo "⚠️ No WebDAV systemd service found"
|
|
||||||
echo "Checking common WebDAV processes:"
|
|
||||||
ps aux | grep -i webdav | grep -v grep || echo "No WebDAV processes found"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 5. Test local connection
|
|
||||||
echo "5. Testing local connection to port 5006..."
|
|
||||||
echo "-------------------------------------------"
|
|
||||||
if command -v nc &> /dev/null; then
|
|
||||||
if nc -zv localhost 5006 2>&1; then
|
|
||||||
echo "✅ Local connection successful"
|
|
||||||
else
|
|
||||||
echo "❌ Local connection failed"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "⚠️ netcat (nc) not available for connection test"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 6. Check network interfaces
|
|
||||||
echo "6. Network interface information..."
|
|
||||||
echo "-------------------------------------------"
|
|
||||||
if command -v ip &> /dev/null; then
|
|
||||||
ip addr show | grep -E "^[0-9]+:|inet " | head -10
|
|
||||||
elif command -v ifconfig &> /dev/null; then
|
|
||||||
ifconfig | grep -E "^[a-z]|inet " | head -10
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 7. Check router/NAT configuration hints
|
|
||||||
echo "7. Router/NAT Configuration Checklist..."
|
|
||||||
echo "-------------------------------------------"
|
|
||||||
echo "Please verify on your router/NAS:"
|
|
||||||
echo " □ Port forwarding: External port 5006 → Internal NAS IP:5006"
|
|
||||||
echo " □ Firewall rules allow incoming connections on port 5006"
|
|
||||||
echo " □ NAT/UPnP is configured correctly"
|
|
||||||
echo " □ External IP matches: $(curl -s ifconfig.me 2>/dev/null || echo 'Unable to determine')"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 8. Common WebDAV configuration files to check
|
|
||||||
echo "8. Common WebDAV configuration locations..."
|
|
||||||
echo "-------------------------------------------"
|
|
||||||
config_locations=(
|
|
||||||
"/etc/apache2/sites-available/*webdav*"
|
|
||||||
"/etc/apache2/conf.d/*webdav*"
|
|
||||||
"/etc/nginx/sites-available/*webdav*"
|
|
||||||
"/etc/nginx/conf.d/*webdav*"
|
|
||||||
"/etc/lighttpd/lighttpd.conf"
|
|
||||||
"/etc/httpd/conf.d/*webdav*"
|
|
||||||
"/usr/local/etc/apache2/*webdav*"
|
|
||||||
)
|
|
||||||
|
|
||||||
for pattern in "${config_locations[@]}"; do
|
|
||||||
for file in $pattern; do
|
|
||||||
if [ -f "$file" ]; then
|
|
||||||
echo "Found: $file"
|
|
||||||
echo " Checking for Listen/ServerName directives..."
|
|
||||||
grep -E "Listen|ServerName|<VirtualHost|listen" "$file" | head -3 || true
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
done
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "=========================================="
|
|
||||||
echo "Diagnostic Complete"
|
|
||||||
echo "=========================================="
|
|
||||||
echo ""
|
|
||||||
echo "Common Issues and Solutions:"
|
|
||||||
echo "1. If service is bound to 127.0.0.1: Change Listen directive to 0.0.0.0:5006"
|
|
||||||
echo "2. If firewall blocks port: Open port 5006 in firewall"
|
|
||||||
echo "3. If router blocks: Configure port forwarding for port 5006"
|
|
||||||
echo "4. If service not running: Start the WebDAV service"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user