Files
StashHandler/README.md
T
bvandeusen 6adfd77236 Add category filtering, default to copy mode, split dev/prod compose
- Default MOVE_MODE changed to copy so qBit can continue seeding
- Add QBIT_CATEGORY env var (default "Stash") to filter torrents
- Split compose into dev (build from source) and prod (pre-built image)
- Fix Dockerfile COPY glob needing trailing slash
- Update README and summary docs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 11:38:17 -05:00

89 lines
3.0 KiB
Markdown

# StashHandler
A Docker service that bridges qBittorrent and Stash. It polls qBittorrent for completed torrents (filtered by category), hashes media files, deduplicates them against a SQLite database, and copies new files into Stash's import directory — preserving originals so seeding can continue.
## Why
- **No reimports** — If you delete a file in Stash, StashHandler remembers its hash and won't import it again.
- **Deduplication** — Duplicate files are caught before they reach Stash.
- **Bulk bootstrap** — Record hashes of your existing Stash library so future downloads are checked against it.
## Quick Start
### Development
```bash
git clone <repo-url> && cd stashhandler
# Edit environment variables in docker-compose.yaml
docker compose up -d --build
```
### Production
```bash
# Copy the example and fill in your values
cp docker-compose.prod.example.yaml docker-compose.yaml
# Edit QBIT_PASSWORD, volume paths, etc.
# Docker Swarm
docker stack deploy -c docker-compose.yaml stash-handler
# Or plain Compose
docker compose up -d
```
The prod compose pulls the pre-built image from `git.fabledsword.com/bvandeusen/stashhandler:latest` and only includes the stash-handler service (qBittorrent and Stash are managed separately).
## Modes
### Daemon (default)
Runs continuously, polling qBittorrent for completed torrents.
```bash
docker run stash-handler # default command is "daemon"
```
### Scan
Bulk-process files on disk. Useful for bootstrapping the dedup database or one-off imports.
```bash
# Record hashes of existing files (no files moved)
docker exec stash-handler python stash_handler.py scan /staging
# Record and import new files to Stash
docker exec stash-handler python stash_handler.py scan --import /staging
# Record hashes from your existing Stash library (mount read-only)
docker exec stash-handler python stash_handler.py scan /stash-library
```
## Configuration
All configuration is via environment variables. No config files needed — works with Docker Swarm secrets and stack deploys.
| Variable | Default | Description |
|---|---|---|
| `QBIT_URL` | `http://qbittorrent:8080` | qBittorrent Web UI URL |
| `QBIT_USERNAME` | `admin` | qBit username |
| `QBIT_PASSWORD` | `adminadmin` | qBit password |
| `STAGING_DIR` | `/staging` | qBit download directory mount |
| `IMPORT_DIR` | `/import` | Stash import directory mount |
| `DB_PATH` | `/data/seen.db` | SQLite database path |
| `POLL_INTERVAL` | `60` | Seconds between polls |
| `MEDIA_EXTENSIONS` | `.mp4,.mkv,.avi,.wmv,.mov,.webm,.flv,.m4v` | Comma-separated extensions |
| `HASH_ALGORITHM` | `sha256` | `sha256` or `blake3` |
| `MOVE_MODE` | `copy` | `copy`, `hardlink`, or `move` |
| `QBIT_CATEGORY` | `Stash` | qBit category to filter torrents by |
| `LOG_LEVEL` | `INFO` | Python log level |
## Volumes
```yaml
volumes:
- /data/staging:/staging:ro # qBit downloads (read-only)
- /data/stash-import:/import # Stash import dir (read-write)
- /data/stash-handler:/data # SQLite database (persistent)
```