6adfd77236
- 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>
89 lines
3.0 KiB
Markdown
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)
|
|
```
|