Quick reference for storage management, troubleshooting, and manual cleanup operations.
The bot runs an APScheduler job every hour that performs the following:
| Task | Interval | What It Does |
|---|---|---|
| Temp cleanup | Every hour | Deletes storage/temp/ files older than 1 hour + their DB rows |
| Archive uploads | Every hour | Moves storage/uploads/ files older than 7 days to storage/archive/ |
| Disk pressure purge | Every hour | If disk >85% full, deletes oldest archive files until <80% |
| Orphan cleanup | Every hour | Removes DB rows for files that no longer exist on disk |
You do not need to run these manually unless you want immediate cleanup.
docker exec shend python -c "from maintenance import print_storage_stats; print_storage_stats()"cd /home/rue/shend
source venv/bin/activate
python -c "from maintenance import print_storage_stats; print_storage_stats()"Example output:
=== Shend Storage Stats ===
Uploads: 9850.50 MB (12 files)
Archive: 0.00 MB (0 files)
Temp: 0.00 MB (0 files)
Total: 9.62 GB / 20.0 GB (48.1%)
===========================
Deletes all files in storage/temp/ regardless of age.
docker exec shend python -c "from maintenance import clear_temp; clear_temp()"Default: 7 days.
docker exec shend python -c "from maintenance import clear_uploads_older_than; clear_uploads_older_than(7)"Default: 90 days.
docker exec shend python -c "from maintenance import clear_archive_older_than; clear_archive_older_than(90)"Removes DB entries for files that were deleted manually.
docker exec shend python -c "import asyncio; from maintenance import cleanup_database_orphans; asyncio.run(cleanup_database_orphans())"Runs: temp cleanup + old uploads + old archive + orphan cleanup + disk pressure check.
docker exec shend python -c "import asyncio; from maintenance import run_full_cleanup; asyncio.run(run_full_cleanup())"docker psdocker logs -f shenddocker logs shend --tail 50sudo systemctl restart shendcd /home/rue/shend
git pull origin main
sudo systemctl restart shenddocker exec -it shend /bin/bashtailscale statustailscale funnel --bg 7777tailscale funnel --https=443 offdocker exec shend sqlite3 /app/data/bot.db ".tables"
docker exec shend sqlite3 /app/data/bot.db "SELECT * FROM uploads LIMIT 5;"cp /home/rue/shend/data/bot.db /home/rue/shend/data/bot.db.backup.$(date +%F)sudo rm /home/rue/shend/data/bot.db
sudo systemctl restart shend/home/rue/shend/
├── storage/
│ ├── uploads/ # Public-facing files (auto-archived after 7 days)
│ ├── archive/ # Long-term storage (auto-purged if disk >85%)
│ └── temp/ # Working files (auto-deleted after 1 hour)
├── data/
│ └── bot.db # SQLite database (WAL mode)
└── .env # Environment variables
| Variable | Default | Description |
|---|---|---|
BOT_TOKEN |
— | Discord bot token (required) |
BASE_URL |
— | Public HTTPS URL from Tailscale Funnel (required) |
STORAGE_PATH |
./storage |
Local storage directory |
DATA_PATH |
./data |
SQLite database directory |
MAX_STORAGE_GB |
20 |
Storage cap in gigabytes |
MAX_UPLOAD_MB |
500 |
Max upload size in megabytes |
TARGET_COMPRESS_MB |
9.5 |
Target compressed file size |
RATE_LIMIT_PER_HOUR |
10 |
Max uploads per user per hour |