1927 lines
52 KiB
Markdown
1927 lines
52 KiB
Markdown
---
|
|
title: Pocket Clips
|
|
description: Integrating Stash
|
|
published: true
|
|
date: 2026-02-22T05:20:31.865Z
|
|
tags:
|
|
editor: markdown
|
|
dateCreated: 2026-02-20T04:48:11.191Z
|
|
---
|
|
|
|
# Pocket Grimoire - Stash Integration Guide
|
|
|
|
**Adding Stash media library manager to Pocket Grimoire using two-instance architecture with ZFS replication**
|
|
|
|
---
|
|
|
|
## Overview
|
|
|
|
This guide extends the Pocket Grimoire deployment to include Stash using a **two-instance architecture**:
|
|
- **Stash-Main** on Netgrimoire watches your entire media library
|
|
- **Stash-Pocket** on Netgrimoire watches only curated personal content (GREEN drive)
|
|
- **Stash-Pocket** replicates to Pocket Grimoire's GREEN drive for offline access
|
|
|
|
This approach provides:
|
|
- Full library management at home (Stash-Main)
|
|
- Curated personal subset with independent database (Stash-Pocket)
|
|
- Automatic synchronization via existing ZFS replication to GREEN drive
|
|
- Read-only browsing on travel with all previews pre-generated
|
|
- Zero CPU load on travel Pi (no scanning/generation)
|
|
|
|
**Key Principle:** All intensive operations happen on Netgrimoire. Pocket Grimoire just serves pre-generated content in read-only mode.
|
|
|
|
**Important:** Stash data lives on the GREEN drive (personal media), NOT on VAULT. VAULT is for backups only.
|
|
|
|
---
|
|
|
|
## Architecture
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────┐
|
|
│ NETGRIMOIRE (Home) │
|
|
├─────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ Stash Instance #1: "Stash-Main" (Port 9999) │
|
|
│ ├─ Watches: ALL media libraries │
|
|
│ ├─ Config: /export/vault/stash-main/config │
|
|
│ ├─ Generated: /export/vault/stash-main/generated │
|
|
│ ├─ Blobs: /export/vault/stash-main/blobs │
|
|
│ ├─ Database: 1-5GB (full library) │
|
|
│ └─ Does NOT sync to Pocket │
|
|
│ │
|
|
│ Stash Instance #2: "Stash-Pocket" (Port 9998) │
|
|
│ ├─ Watches: ONLY Green/Pocket (personal content) │
|
|
│ ├─ Location: /export/Green/Pocket/ │
|
|
│ │ ├── media/library/ (personal media) │
|
|
│ │ └── stash/ (Stash-Pocket data) │
|
|
│ │ ├── config/ (database) │
|
|
│ │ ├── generated/ (previews) │
|
|
│ │ └── blobs/ (markers) │
|
|
│ ├─ Database: 200MB-1GB (personal subset) │
|
|
│ └─ SYNCS to Pocket GREEN drive via ZFS │
|
|
│ │
|
|
└─────────────────────────────────────────────────────┘
|
|
↓ ZFS Send (syncoid)
|
|
(vault/Green/Pocket → greenpg/Pocket)
|
|
↓
|
|
┌─────────────────────────────────────────────────────┐
|
|
│ POCKET GRIMOIRE (Travel) │
|
|
├─────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ GREEN Drive (greenpg pool): │
|
|
│ └─ /srv/greenpg/Pocket/ (dataset from sync) │
|
|
│ ├─ media/library/ (media files) │
|
|
│ └─ stash/ (Stash data) │
|
|
│ │
|
|
│ Stash Instance: "Stash-Pocket" (Port 9999) │
|
|
│ ├─ Watches: GREEN media only (read-only) │
|
|
│ ├─ Location: /srv/greenpg/Pocket/ │
|
|
│ │ ├── media/library/ (synced media) │
|
|
│ │ └── stash/ (synced, read-only) │
|
|
│ │ ├── config/ (synced database) │
|
|
│ │ ├── generated/ (synced previews) │
|
|
│ │ └── blobs/ (synced markers) │
|
|
│ ├─ Same database as Netgrimoire Stash-Pocket │
|
|
│ └─ Browse only - no scanning or generation │
|
|
│ │
|
|
└─────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## Why Two Instances?
|
|
|
|
### Benefits of Two-Instance Architecture
|
|
|
|
✅ **Stash-Main (Port 9999):**
|
|
- Manages your entire home media library
|
|
- Heavy operations (scanning, tagging, preview generation)
|
|
- Full featured - edit, organize, tag anything
|
|
- Stays on Netgrimoire (doesn't sync to Pocket)
|
|
|
|
✅ **Stash-Pocket (Port 9998 at home, 9999 on travel):**
|
|
- Manages only curated personal content (GREEN drive)
|
|
- Smaller database (faster, lighter)
|
|
- Independent from main library
|
|
- Syncs to Pocket Grimoire's GREEN drive automatically
|
|
- Preview personal setup before trips
|
|
|
|
✅ **Separation of Concerns:**
|
|
- Main library can be massive (thousands of videos)
|
|
- Personal subset is manageable (hundreds of videos)
|
|
- No confusion about what's available where
|
|
- Changes to main library don't affect travel copy
|
|
- Faster sync times (only GREEN data replicates)
|
|
|
|
---
|
|
|
|
## Storage Requirements
|
|
|
|
### On Netgrimoire
|
|
|
|
**Stash-Main (Does NOT sync):**
|
|
```
|
|
Location: /export/vault/stash-main/
|
|
Database: 1-5GB (depends on library size)
|
|
Generated previews: 50-200GB (depends on settings)
|
|
Blobs/markers: 5-20GB
|
|
─────────────────────────────────────────────
|
|
Total: ~56-225GB (stays on Netgrimoire)
|
|
```
|
|
|
|
**Stash-Pocket (DOES sync to GREEN drive):**
|
|
```
|
|
Location: /export/Green/Pocket/stash/
|
|
Database: 200MB-1GB (smaller subset)
|
|
Generated previews: 5-20GB
|
|
Blobs/markers: 1-5GB
|
|
─────────────────────────────────────────────
|
|
Total: ~6-26GB (syncs to Pocket GREEN)
|
|
```
|
|
|
|
**Personal Media (syncs to GREEN drive):**
|
|
```
|
|
Location: /export/Green/Pocket/media/
|
|
Content: 500GB-1TB (curated for travel)
|
|
─────────────────────────────────────────────
|
|
Total Green/Pocket: ~506GB-1TB (vault/Green/Pocket dataset)
|
|
```
|
|
|
|
### On Pocket Grimoire (GREEN Drive)
|
|
|
|
```
|
|
Location: /srv/greenpg/Pocket/
|
|
Stash data: ~6-26GB (synced from Netgrimoire)
|
|
Media files: ~500GB-1TB (synced from Netgrimoire)
|
|
─────────────────────────────────────────────
|
|
Total: ~506GB-1TB on GREEN SSD
|
|
|
|
This fits comfortably on a 2TB+ GREEN SSD.
|
|
```
|
|
|
|
**Note:** VAULT drive contains backups only (no Stash, no media).
|
|
|
|
---
|
|
|
|
## Resource Impact
|
|
|
|
### Updated Resource Profile (With Stash)
|
|
|
|
**Netgrimoire (Running Two Instances):**
|
|
|
|
Idle:
|
|
```
|
|
Stash-Main: ~400MB RAM
|
|
Stash-Pocket: ~300MB RAM (smaller database)
|
|
────────────────────────────
|
|
Total: ~700MB RAM
|
|
CPU: <5%
|
|
```
|
|
|
|
During operations:
|
|
```
|
|
Stash-Main (scanning): ~1-2GB RAM, 80%+ CPU
|
|
Stash-Pocket (scanning): ~500MB RAM, 40% CPU
|
|
Note: Run intensive tasks one at a time
|
|
```
|
|
|
|
**Pocket Grimoire (Single Instance, Read-Only):**
|
|
|
|
Idle:
|
|
```
|
|
Wiki.js + PostgreSQL: ~250MB RAM
|
|
Jellyfin (idle): ~150MB RAM
|
|
Stash-Pocket: ~200MB RAM
|
|
ZFS ARC: ~512MB RAM
|
|
System: ~200MB RAM
|
|
─────────────────────────────────
|
|
Total: ~1.3GB / 8GB RAM ✓
|
|
CPU: <10%
|
|
Temperature: Cool
|
|
```
|
|
|
|
Browsing Stash:
|
|
```
|
|
Stash-Pocket (active): ~300MB RAM
|
|
Other services: ~1.1GB RAM
|
|
─────────────────────────────────
|
|
Total: ~1.4GB / 8GB RAM ✓
|
|
CPU: <15%
|
|
Temperature: Cool to Warm
|
|
```
|
|
|
|
Media playback + Stash:
|
|
```
|
|
Jellyfin (serving): ~200MB RAM
|
|
Stash (browsing): ~300MB RAM
|
|
Wiki.js + PostgreSQL: ~250MB RAM
|
|
ZFS ARC: ~512MB RAM
|
|
System: ~200MB RAM
|
|
─────────────────────────────────
|
|
Total: ~1.5GB / 8GB RAM ✓
|
|
Still plenty of headroom
|
|
```
|
|
|
|
---
|
|
|
|
## Installation: Netgrimoire (Home)
|
|
|
|
### 1. Create Directory Structure
|
|
|
|
```bash
|
|
# Create Stash-Main directories (NOT in Green folder - won't sync)
|
|
sudo mkdir -p /export/vault/stash-main/{config,generated,blobs,cache}
|
|
sudo chown -R 1000:1000 /export/vault/stash-main
|
|
sudo chmod -R 755 /export/vault/stash-main
|
|
|
|
# Stash-Pocket directories in existing Green/Pocket dataset
|
|
# Your dataset: vault/Green/Pocket mounted at /export/Green/Pocket
|
|
sudo mkdir -p /export/Green/Pocket/stash/{config,generated,blobs,cache}
|
|
sudo mkdir -p /export/Green/Pocket/media/library/{movies,tv}
|
|
sudo chown -R 1000:1000 /export/Green/Pocket
|
|
sudo chmod -R 755 /export/Green/Pocket
|
|
```
|
|
|
|
**Verify structure:**
|
|
```bash
|
|
tree -L 2 /export/vault/stash-main
|
|
tree -L 3 /export/Green/Pocket
|
|
# Should show:
|
|
# /export/Green/Pocket/
|
|
# ├── stash/
|
|
# │ ├── config/
|
|
# │ ├── generated/
|
|
# │ ├── blobs/
|
|
# │ └── cache/
|
|
# └── media/
|
|
# └── library/
|
|
```
|
|
|
|
### 2. Curate Pocket Media Content
|
|
|
|
**Copy or move curated travel content to Pocket location:**
|
|
|
|
```bash
|
|
# Example: Copy favorite movies to Pocket
|
|
cp /export/vault/media/library/movies/favorites/*.mp4 \
|
|
/export/vault/Green/Pocket/media/library/movies/
|
|
|
|
# Example: Copy specific TV show seasons
|
|
cp -r /export/vault/media/library/tv/ShowName/Season01 \
|
|
/export/vault/Green/Pocket/media/library/tv/
|
|
|
|
# Or organize a dedicated travel collection
|
|
mkdir -p /export/vault/Green/Pocket/media/library/travel-collection
|
|
# ... add curated content ...
|
|
```
|
|
|
|
**Important:** This is your travel media library. Keep it manageable (500GB-1TB).
|
|
|
|
### 3. Stash-Main Docker Compose
|
|
|
|
**Create directory:**
|
|
```bash
|
|
mkdir -p /srv/netgrimoire/stacks/stash-main
|
|
```
|
|
|
|
**File:** `/srv/netgrimoire/stacks/stash-main/docker-compose.yml`
|
|
|
|
```yaml
|
|
services:
|
|
stash-main:
|
|
image: stashapp/stash:latest
|
|
container_name: netgrimoire_stash_main
|
|
environment:
|
|
- STASH_STASH=/data/
|
|
- STASH_GENERATED=/generated/
|
|
- STASH_CACHE=/cache/
|
|
- STASH_BLOBS=/blobs/
|
|
- TZ=America/Chicago
|
|
volumes:
|
|
# Stash-Main data (NOT in Pocket directory - won't sync)
|
|
- /export/vault/stash-main/config:/root/.stash
|
|
- /export/vault/stash-main/generated:/generated
|
|
- /export/vault/stash-main/blobs:/blobs
|
|
- /export/vault/stash-main/cache:/cache
|
|
|
|
# Watch ALL media libraries
|
|
- /export/vault/media:/data:ro
|
|
|
|
# Optionally also include Pocket media in main view
|
|
# - /export/vault/Green/Pocket/media:/data/pocket:ro
|
|
ports:
|
|
- "9999:9999"
|
|
restart: unless-stopped
|
|
```
|
|
|
|
**Start Stash-Main:**
|
|
```bash
|
|
cd /srv/netgrimoire/stacks/stash-main
|
|
docker compose up -d
|
|
|
|
# Check logs
|
|
docker logs -f netgrimoire_stash_main
|
|
|
|
# Access: http://netgrimoire.local:9999
|
|
```
|
|
|
|
### 4. Stash-Pocket Docker Compose
|
|
|
|
**Create directory:**
|
|
```bash
|
|
mkdir -p /srv/netgrimoire/stacks/stash-pocket
|
|
```
|
|
|
|
**File:** `/srv/netgrimoire/stacks/stash-pocket/docker-compose.yml`
|
|
|
|
```yaml
|
|
services:
|
|
stash-pocket:
|
|
image: stashapp/stash:latest
|
|
container_name: netgrimoire_stash_pocket
|
|
environment:
|
|
- STASH_STASH=/data/
|
|
- STASH_GENERATED=/generated/
|
|
- STASH_CACHE=/cache/
|
|
- STASH_BLOBS=/blobs/
|
|
- TZ=America/Chicago
|
|
volumes:
|
|
# Stash-Pocket data (IN Pocket directory - will sync)
|
|
- /export/vault/Green/Pocket/stash/config:/root/.stash
|
|
- /export/vault/Green/Pocket/stash/generated:/generated
|
|
- /export/vault/Green/Pocket/stash/blobs:/blobs
|
|
- /export/vault/Green/Pocket/stash/cache:/cache
|
|
|
|
# Watch ONLY Pocket media
|
|
- /export/vault/Green/Pocket/media:/data:ro
|
|
ports:
|
|
- "9998:9999" # Different external port to avoid conflict
|
|
restart: unless-stopped
|
|
```
|
|
|
|
**Note:** Container uses port 9999 internally, but exposed as 9998 externally to avoid conflict with Stash-Main.
|
|
|
|
**Start Stash-Pocket:**
|
|
```bash
|
|
cd /srv/netgrimoire/stacks/stash-pocket
|
|
docker compose up -d
|
|
|
|
# Check logs
|
|
docker logs -f netgrimoire_stash_pocket
|
|
|
|
# Access: http://netgrimoire.local:9998
|
|
```
|
|
|
|
**Verify both running:**
|
|
```bash
|
|
docker ps | grep stash
|
|
# Should show:
|
|
# netgrimoire_stash_main (port 9999)
|
|
# netgrimoire_stash_pocket (port 9998)
|
|
```
|
|
|
|
### 5. Configure Stash-Main
|
|
|
|
**Access:** `http://netgrimoire.local:9999`
|
|
|
|
1. **Initial Setup Wizard:**
|
|
- Set admin password
|
|
- Configure paths (default /data should work)
|
|
- Complete setup
|
|
|
|
2. **Add Libraries:**
|
|
- Settings → Library
|
|
- Add folder: `/data/library` (or your structure)
|
|
- Save
|
|
|
|
3. **Run Initial Scan:**
|
|
- Tasks → Scan
|
|
- Wait for completion (can take hours for large libraries)
|
|
|
|
4. **Configure Preview Generation:**
|
|
- Settings → Tasks → Generate
|
|
- Video encoding: VP9 or H.264
|
|
- Resolution: 720p (good quality, reasonable size)
|
|
- Preview duration: 20-60 seconds
|
|
- Enable image previews
|
|
- Enable sprites
|
|
|
|
5. **Generate Previews:**
|
|
- Tasks → Generate → Previews
|
|
- This is CPU intensive - let run overnight
|
|
- Can take many hours for large libraries
|
|
|
|
6. **Organize and Tag:**
|
|
- Tag performers, studios, scenes
|
|
- Create collections, galleries
|
|
- Add markers, metadata
|
|
- This is your full-featured home library
|
|
|
|
### 6. Configure Stash-Pocket
|
|
|
|
**Access:** `http://netgrimoire.local:9998`
|
|
|
|
1. **Initial Setup Wizard:**
|
|
- Set admin password (can be same as Stash-Main)
|
|
- Configure paths (default /data should work)
|
|
- Complete setup
|
|
|
|
2. **Add Library:**
|
|
- Settings → Library
|
|
- Add folder: `/data/library`
|
|
- Save
|
|
|
|
3. **Run Initial Scan:**
|
|
- Tasks → Scan
|
|
- Should be much faster (smaller library)
|
|
- Wait for completion
|
|
|
|
4. **Configure Preview Generation:**
|
|
- Use same settings as Stash-Main
|
|
- Settings → Tasks → Generate
|
|
- Resolution: 720p
|
|
- Preview duration: 20-60 seconds
|
|
|
|
5. **Generate Previews:**
|
|
- Tasks → Generate → Previews
|
|
- Much faster than Stash-Main (fewer videos)
|
|
- Let complete before first trip
|
|
|
|
6. **Organize (Optional):**
|
|
- Tag travel-specific content
|
|
- Create "Travel Favorites" collections
|
|
- Can copy/import tags from Stash-Main if desired
|
|
- Or keep separate organization
|
|
|
|
**Why configure Stash-Pocket separately?**
|
|
- Independent database from Stash-Main
|
|
- Travel-specific organization
|
|
- Can have different preview settings (optimize for size)
|
|
- Preview what will be available on travel
|
|
|
|
### 7. Verify Data in Pocket Directory
|
|
|
|
```bash
|
|
# Check Stash-Pocket database exists
|
|
ls -lh /export/vault/Green/Pocket/stash/config/
|
|
# Should show: stash-go.sqlite (database file)
|
|
|
|
# Check previews generated
|
|
ls -lh /export/vault/Green/Pocket/stash/generated/
|
|
# Should show: many .webp or .mp4 preview files
|
|
|
|
# Check media is present
|
|
ls -lh /export/vault/Green/Pocket/media/library/movies/
|
|
# Should show: your curated travel media
|
|
```
|
|
|
|
---
|
|
|
|
## Installation: Pocket Grimoire (Travel)
|
|
|
|
### 1. Wait for Initial Sync
|
|
|
|
**Your existing ZFS sync handles everything:**
|
|
|
|
```bash
|
|
# This already exists in your sync script:
|
|
syncoid --no-sync-snap --recursive \
|
|
--sshkey "${SSH_KEY}" \
|
|
"root@${NETGRIMOIRE}:vault/Green/Pocket" \
|
|
"vaultpg/Green/Pocket"
|
|
```
|
|
|
|
**This syncs:**
|
|
- ✅ Stash-Pocket database
|
|
- ✅ Stash-Pocket previews
|
|
- ✅ Stash-Pocket blobs/markers
|
|
- ✅ Pocket media files
|
|
- ✅ Wiki, photos, documents (already syncing)
|
|
|
|
**Initial sync time:**
|
|
- Stash data: 10-30 minutes
|
|
- Media files: 1-4 hours (depending on size)
|
|
- Total: 1-5 hours for first sync
|
|
|
|
**Check sync status:**
|
|
```bash
|
|
# On Pocket Grimoire
|
|
tail -f /var/log/pocketgrimoire-sync.log
|
|
|
|
# Verify data arrived
|
|
ls /srv/vaultpg/Green/Pocket/stash/
|
|
ls /srv/vaultpg/Green/Pocket/media/
|
|
```
|
|
|
|
### 2. Verify Synced Data
|
|
|
|
```bash
|
|
# SSH into Pocket Grimoire
|
|
ssh user@pocket-grimoire.local
|
|
|
|
# Check Stash database
|
|
ls -lh /srv/vaultpg/Green/Pocket/stash/config/
|
|
# Should show: stash-go.sqlite
|
|
|
|
# Check previews
|
|
ls /srv/vaultpg/Green/Pocket/stash/generated/ | wc -l
|
|
# Should show: hundreds of preview files
|
|
|
|
# Check media
|
|
du -sh /srv/vaultpg/Green/Pocket/media/
|
|
# Should show: 500GB-1TB
|
|
```
|
|
|
|
### 3. Create Stash Docker Compose
|
|
|
|
**Create directory:**
|
|
```bash
|
|
mkdir -p /srv/pocket-grimoire/stacks/stash
|
|
mkdir -p /srv/pocket-grimoire/data/stash/cache
|
|
```
|
|
|
|
**File:** `/srv/pocket-grimoire/stacks/stash/docker-compose.yml`
|
|
|
|
```yaml
|
|
services:
|
|
stash:
|
|
image: stashapp/stash:latest
|
|
container_name: pocketgrimoire_stash
|
|
environment:
|
|
- STASH_STASH=/data/
|
|
- STASH_GENERATED=/generated/
|
|
- STASH_CACHE=/cache/
|
|
- STASH_BLOBS=/blobs/
|
|
- TZ=America/Chicago
|
|
volumes:
|
|
# Point to synced Pocket directory on GREEN drive (READ-ONLY)
|
|
- /srv/greenpg/Pocket/stash/config:/root/.stash:ro
|
|
- /srv/greenpg/Pocket/stash/generated:/generated:ro
|
|
- /srv/greenpg/Pocket/stash/blobs:/blobs:ro
|
|
|
|
# Local cache only (writable, not synced)
|
|
- /srv/pocket-grimoire/data/stash/cache:/cache
|
|
|
|
# Media location on GREEN drive (read-only)
|
|
- /srv/greenpg/Pocket/media:/data:ro
|
|
ports:
|
|
- "9999:9999" # Standard port on Pocket (no conflict)
|
|
restart: unless-stopped
|
|
```
|
|
|
|
**Note the `:ro` flags** - Everything except local cache is read-only.
|
|
|
|
### 4. Start Stash on Pocket Grimoire
|
|
|
|
```bash
|
|
cd /srv/pocket-grimoire/stacks/stash
|
|
docker compose up -d
|
|
|
|
# Check logs
|
|
docker logs -f pocketgrimoire_stash
|
|
|
|
# Verify running
|
|
docker ps | grep stash
|
|
```
|
|
|
|
### 5. Access and Verify
|
|
|
|
**Access:** `http://pocket-grimoire.local:9999`
|
|
|
|
**Should see:**
|
|
- Same library as Netgrimoire Stash-Pocket
|
|
- All previews available
|
|
- All scene markers working
|
|
- All metadata present
|
|
- Works fully offline
|
|
|
|
**Verify read-only mode:**
|
|
- Try to edit a scene → Should fail with permission error
|
|
- Try to scan library → Should fail
|
|
- Try to generate previews → Should fail
|
|
- This confirms read-only mode is working
|
|
|
|
### 6. Disable Background Tasks
|
|
|
|
**In Stash UI:**
|
|
- Settings → Tasks
|
|
- Disable all automatic tasks:
|
|
- ❌ Auto-scan
|
|
- ❌ Auto-tag
|
|
- ❌ Auto-preview generation
|
|
- ❌ Auto-cleanup
|
|
- Save settings
|
|
|
|
**Why?** Even though filesystem is read-only, these tasks will try to run and fail. Better to disable.
|
|
|
|
---
|
|
|
|
## ZFS Replication Configuration
|
|
|
|
### Your Existing Sync Script Already Works!
|
|
|
|
**File:** `/usr/local/sbin/pocketgrimoire-zfs-pull.sh`
|
|
|
|
**Current sync (should already include this):**
|
|
```bash
|
|
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
SRC_HOST="netgrimoire.local"
|
|
SSH_KEY="/srv/pocket-grimoire/keys/zfs_pull_ro"
|
|
|
|
# Sync vault/Green/Pocket to GREEN drive (greenpg/Pocket)
|
|
syncoid --no-sync-snap \
|
|
--sshkey "${SSH_KEY}" \
|
|
"root@${SRC_HOST}:vault/Green/Pocket" \
|
|
"greenpg/Pocket"
|
|
|
|
# This single command syncs:
|
|
# - /export/Green/Pocket/stash/ → Stash-Pocket data
|
|
# - /export/Green/Pocket/media/ → Media files
|
|
# All Pocket data syncs to GREEN drive automatically
|
|
```
|
|
|
|
**No additional sync commands needed!** ✅
|
|
|
|
**Stash-Main data does NOT sync** (it's in `/export/vault/stash-main/`, outside Pocket directory).
|
|
|
|
**Note:** The sync destination is `greenpg/Pocket` on the GREEN drive, NOT `vaultpg`. Stash and media data live on GREEN, not VAULT.
|
|
|
|
### Sync Frequency
|
|
|
|
**Your existing timer:** Every 6 hours
|
|
|
|
This is perfect for Stash:
|
|
- Database changes sync regularly
|
|
- New previews sync automatically
|
|
- New media syncs when added
|
|
|
|
**To sync immediately (before trips):**
|
|
```bash
|
|
sudo systemctl start pocketgrimoire-sync.service
|
|
tail -f /var/log/pocketgrimoire-sync.log
|
|
```
|
|
|
|
---
|
|
|
|
## Workflow
|
|
|
|
### At Home: Adding Content for Travel
|
|
|
|
**1. Curate new content:**
|
|
```bash
|
|
# On Netgrimoire
|
|
cp /export/vault/media/library/movies/new-favorites/*.mp4 \
|
|
/export/vault/Green/Pocket/media/library/movies/
|
|
```
|
|
|
|
**2. Scan Stash-Pocket:**
|
|
```
|
|
Open: http://netgrimoire.local:9998
|
|
Tasks → Scan
|
|
Wait for completion
|
|
```
|
|
|
|
**3. Generate previews (if needed):**
|
|
```
|
|
Tasks → Generate → Previews
|
|
Wait for completion
|
|
```
|
|
|
|
**4. Let sync happen (automatic):**
|
|
- Next 6-hour sync cycle picks up changes
|
|
- Or trigger manually: `sudo systemctl start pocketgrimoire-sync.service`
|
|
|
|
**5. Verify on Pocket Grimoire:**
|
|
```
|
|
Open: http://pocket-grimoire.local:9999
|
|
Should show new content after sync
|
|
```
|
|
|
|
### At Home: Previewing Travel Setup
|
|
|
|
**Access Stash-Pocket on Netgrimoire:**
|
|
```
|
|
http://netgrimoire.local:9998
|
|
```
|
|
|
|
**This shows exactly what will be available on Pocket Grimoire:**
|
|
- Same library
|
|
- Same previews
|
|
- Same organization
|
|
- Test before traveling
|
|
|
|
### While Traveling: Browsing Content
|
|
|
|
**On Pocket Grimoire:**
|
|
```
|
|
http://pocket-grimoire.local:9999
|
|
```
|
|
|
|
**Features available offline:**
|
|
- ✅ Browse entire Pocket library
|
|
- ✅ View all previews
|
|
- ✅ See scene markers
|
|
- ✅ Search and filter
|
|
- ✅ View performer/studio info
|
|
- ❌ Cannot edit or tag (read-only)
|
|
- ❌ Cannot scan or generate (read-only)
|
|
|
|
**Play media:**
|
|
- Click video in Stash
|
|
- Opens in browser player
|
|
- Or copy path and open in Jellyfin
|
|
- Or use StashApp on Onn boxes
|
|
|
|
### If You Need to Edit While Traveling
|
|
|
|
**VPN back to Netgrimoire:**
|
|
1. Connect Beryl AX to hotel WiFi
|
|
2. WireGuard VPN connects to Netgrimoire
|
|
3. Access Netgrimoire Stash-Pocket: `http://netgrimoire.local:9998`
|
|
4. Make edits there
|
|
5. Changes sync on next cycle
|
|
|
|
---
|
|
|
|
## Accessing Stash
|
|
|
|
### From Web Browser
|
|
|
|
**At Home (Netgrimoire):**
|
|
```
|
|
Stash-Main (Full Library): http://netgrimoire.local:9999
|
|
Stash-Pocket (Travel Subset): http://netgrimoire.local:9998
|
|
```
|
|
|
|
**While Traveling (Pocket Grimoire):**
|
|
```
|
|
Stash-Pocket (Travel Subset): http://pocket-grimoire.local:9999
|
|
```
|
|
|
|
**From Laptop (via browser):**
|
|
- Connect to portapotty WiFi
|
|
- Open browser to above URLs
|
|
- Works same as Netgrimoire
|
|
|
|
### From Onn Streaming Boxes
|
|
|
|
**Install StashApp for Android TV:**
|
|
- See "Onn 4K Streaming Box Setup Guide" for detailed instructions
|
|
- Download APK: https://github.com/damontecres/StashAppAndroidTV/releases
|
|
- Sideload onto Onn boxes
|
|
|
|
**Configure StashApp:**
|
|
```
|
|
Server URL: http://pocket-grimoire.local:9999
|
|
Or: http://10.0.0.10:9999 (if .local doesn't resolve)
|
|
API Key: (if required - found in Stash settings)
|
|
```
|
|
|
|
**Features on Onn:**
|
|
- Browse Stash library
|
|
- View previews and scene markers
|
|
- Play videos directly
|
|
- Search and filter
|
|
- Full touch/remote control
|
|
|
|
### From Phone/Tablet
|
|
|
|
**Via Web Browser:**
|
|
```
|
|
Connect to portapotty WiFi
|
|
Open: http://pocket-grimoire.local:9999
|
|
Mobile-responsive interface works well
|
|
```
|
|
|
|
---
|
|
|
|
## Service Access Summary
|
|
|
|
**Updated with Stash:**
|
|
|
|
```
|
|
When connected to portapotty network:
|
|
|
|
Wiki.js: http://pocket-grimoire.local:3000
|
|
Jellyfin: http://pocket-grimoire.local:8096
|
|
Stash: http://pocket-grimoire.local:9999 ← NEW
|
|
File Browser: http://pocket-grimoire.local:8080
|
|
Dozzle: http://pocket-grimoire.local:8888
|
|
SSH: ssh user@pocket-grimoire.local
|
|
NFS Media: nfs://pocket-grimoire.local/srv/mediapg
|
|
Router Admin: http://192.168.8.1
|
|
|
|
At Home (Netgrimoire):
|
|
Stash-Main: http://netgrimoire.local:9999
|
|
Stash-Pocket: http://netgrimoire.local:9998
|
|
```
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
### Stash Won't Start on Pocket Grimoire
|
|
|
|
**Check Docker container status:**
|
|
```bash
|
|
docker ps | grep stash
|
|
docker logs pocketgrimoire_stash
|
|
```
|
|
|
|
**Common issues:**
|
|
- **ZFS datasets not mounted:**
|
|
```bash
|
|
zfs list | grep Pocket
|
|
sudo zfs mount -a
|
|
```
|
|
|
|
- **Permissions denied:**
|
|
```bash
|
|
ls -ld /srv/vaultpg/Green/Pocket/stash/
|
|
# Should show ownership 1000:1000
|
|
sudo chown -R 1000:1000 /srv/vaultpg/Green/Pocket/stash/
|
|
```
|
|
|
|
- **Port conflict:**
|
|
```bash
|
|
sudo netstat -tlnp | grep 9999
|
|
# If another service is using port 9999, change in docker-compose.yml
|
|
```
|
|
|
|
### Stash Shows "Database is locked"
|
|
|
|
**This is expected - read-only mode is working correctly.**
|
|
|
|
The database file is mounted read-only (`:ro` flag), so Stash cannot write to it.
|
|
|
|
**If you need to make changes:**
|
|
1. VPN to Netgrimoire
|
|
2. Access: `http://netgrimoire.local:9998`
|
|
3. Edit on Netgrimoire Stash-Pocket
|
|
4. Changes sync on next cycle
|
|
|
|
### Previews Not Showing on Pocket Grimoire
|
|
|
|
**Verify previews synced:**
|
|
```bash
|
|
ls /srv/vaultpg/Green/Pocket/stash/generated/
|
|
# Should show many .webp or .mp4 files
|
|
|
|
du -sh /srv/vaultpg/Green/Pocket/stash/generated/
|
|
# Should show several GB
|
|
```
|
|
|
|
**If empty:**
|
|
- Previews not generated on Netgrimoire yet
|
|
- Generate: `http://netgrimoire.local:9998` → Tasks → Generate
|
|
- Sync hasn't completed
|
|
- Check: `tail -f /var/log/pocketgrimoire-sync.log`
|
|
- Sync failed
|
|
- Check logs for errors
|
|
- Manually trigger: `sudo systemctl start pocketgrimoire-sync.service`
|
|
|
|
### Media Files Not Found
|
|
|
|
**Check media synced:**
|
|
```bash
|
|
ls /srv/vaultpg/Green/Pocket/media/library/movies/
|
|
# Should show video files
|
|
|
|
du -sh /srv/vaultpg/Green/Pocket/media/
|
|
# Should show 500GB-1TB
|
|
```
|
|
|
|
**If empty:**
|
|
- Media not in Pocket directory on Netgrimoire
|
|
- Check: `/export/vault/Green/Pocket/media/`
|
|
- Sync hasn't completed (media takes longest)
|
|
- Wait or trigger manual sync
|
|
- Check progress: `zfs list vaultpg/Green/Pocket`
|
|
|
|
**Verify Docker volume mount:**
|
|
```bash
|
|
docker inspect pocketgrimoire_stash | grep -A 10 Mounts
|
|
# Should show /srv/vaultpg/Green/Pocket/media mounted as /data
|
|
```
|
|
|
|
### Sync Takes Too Long
|
|
|
|
**Check what's being synced:**
|
|
```bash
|
|
# Watch sync progress
|
|
tail -f /var/log/pocketgrimoire-sync.log
|
|
|
|
# Check dataset sizes
|
|
zfs list | grep Pocket
|
|
```
|
|
|
|
**Optimization tips:**
|
|
|
|
1. **Reduce preview quality on Netgrimoire:**
|
|
- Stash-Pocket settings: Lower resolution (480p instead of 720p)
|
|
- Smaller files = faster sync
|
|
|
|
2. **Sync less frequently:**
|
|
- Change timer from 6h to 12h or 24h
|
|
- Edit: `/etc/systemd/system/pocketgrimoire-sync.timer`
|
|
|
|
3. **Compress during sync:**
|
|
```bash
|
|
syncoid --compress=lz4 \
|
|
"root@${SRC_HOST}:vault/Green/Pocket" \
|
|
"vaultpg/Green/Pocket"
|
|
```
|
|
|
|
4. **Bandwidth limit (if needed):**
|
|
```bash
|
|
syncoid --bwlimit=50M \
|
|
"root@${SRC_HOST}:vault/Green/Pocket" \
|
|
"vaultpg/Green/Pocket"
|
|
```
|
|
|
|
### Stash API Key Issues (StashApp)
|
|
|
|
**If StashApp asks for API key:**
|
|
|
|
**On Netgrimoire Stash-Pocket:**
|
|
```
|
|
http://netgrimoire.local:9998
|
|
Settings → Security → API Key
|
|
Generate key if not present
|
|
Copy key
|
|
```
|
|
|
|
**API key is in config file (synced to Pocket):**
|
|
```bash
|
|
# On Netgrimoire
|
|
cat /export/vault/Green/Pocket/stash/config/config.yml | grep api_key
|
|
|
|
# On Pocket (after sync)
|
|
cat /srv/vaultpg/Green/Pocket/stash/config/config.yml | grep api_key
|
|
```
|
|
|
|
**Configure StashApp:**
|
|
- Settings → Server → API Key
|
|
- Paste key
|
|
- Connect
|
|
|
|
**Note:** API key syncs with config, so should be same on both systems.
|
|
|
|
### Two Instances Conflict on Netgrimoire
|
|
|
|
**Problem:** Both Stash instances try to use same port
|
|
|
|
**Solution:** Already handled - different external ports
|
|
- Stash-Main: External 9999 → Internal 9999
|
|
- Stash-Pocket: External 9998 → Internal 9999
|
|
|
|
**Verify no conflict:**
|
|
```bash
|
|
sudo netstat -tlnp | grep 9999
|
|
# Should show: netgrimoire_stash_main
|
|
|
|
sudo netstat -tlnp | grep 9998
|
|
# Should show: netgrimoire_stash_pocket
|
|
```
|
|
|
|
---
|
|
|
|
## Optimization Tips
|
|
|
|
### Reduce Storage Usage
|
|
|
|
**On Netgrimoire (affects Pocket via sync):**
|
|
|
|
1. **Lower preview quality for Stash-Pocket:**
|
|
```
|
|
http://netgrimoire.local:9998
|
|
Settings → Tasks → Generate
|
|
- Video resolution: 480p (instead of 720p)
|
|
- Lower bitrate
|
|
- Shorter duration (20s instead of 60s)
|
|
```
|
|
|
|
2. **Disable sprite generation:**
|
|
```
|
|
Settings → Tasks → Generate
|
|
- Disable sprite generation
|
|
- Just use video previews
|
|
- Saves significant space
|
|
```
|
|
|
|
3. **Selective preview generation:**
|
|
```
|
|
Don't generate previews for everything
|
|
Only generate for favorites or frequently viewed
|
|
```
|
|
|
|
### Speed Up Initial Sync
|
|
|
|
**First sync only:**
|
|
```bash
|
|
# Use compression
|
|
syncoid --compress=lz4 \
|
|
--sshkey "${SSH_KEY}" \
|
|
"root@${NETGRIMOIRE}:vault/Green/Pocket" \
|
|
"vaultpg/Green/Pocket"
|
|
```
|
|
|
|
**Subsequent syncs are incremental (much faster).**
|
|
|
|
### Reduce Preview Generation Load
|
|
|
|
**On Netgrimoire:**
|
|
- Generate previews during off-hours (overnight)
|
|
- Use Stash Task Scheduler
|
|
- Limit concurrent preview generation
|
|
- Lower thread count for generation
|
|
- Settings → System → Parallel Tasks: 4 (instead of 8+)
|
|
|
|
---
|
|
|
|
## Maintenance
|
|
|
|
### Weekly (While at Home)
|
|
|
|
**On Netgrimoire:**
|
|
```bash
|
|
# Check both Stash instances running
|
|
docker ps | grep stash
|
|
|
|
# Verify Pocket directory health
|
|
du -sh /export/vault/Green/Pocket/
|
|
zfs list | grep Pocket
|
|
|
|
# Check for database integrity (optional)
|
|
# Stash-Main: http://netgrimoire.local:9999 → Tasks → Optimize Database
|
|
# Stash-Pocket: http://netgrimoire.local:9998 → Tasks → Optimize Database
|
|
```
|
|
|
|
**On Pocket Grimoire:**
|
|
```bash
|
|
# Verify sync is working
|
|
tail -n 100 /var/log/pocketgrimoire-sync.log
|
|
|
|
# Check Stash accessible
|
|
curl -s http://localhost:9999 | grep -i stash
|
|
|
|
# Check storage usage
|
|
df -h /srv/vaultpg
|
|
```
|
|
|
|
### Monthly
|
|
|
|
**On Netgrimoire:**
|
|
```bash
|
|
# Run manual scan if auto-scan disabled
|
|
# Stash-Pocket: Tasks → Scan
|
|
|
|
# Clean up orphaned files (if any)
|
|
# Tasks → Clean
|
|
|
|
# Check database integrity
|
|
# Tasks → Optimize Database
|
|
|
|
# ZFS scrub
|
|
sudo zfs scrub vault/Green/Pocket
|
|
```
|
|
|
|
**On Pocket Grimoire:**
|
|
```bash
|
|
# Verify dataset health
|
|
sudo zpool status vaultpg
|
|
|
|
# Check for errors in sync logs
|
|
grep -i error /var/log/pocketgrimoire-sync.log
|
|
|
|
# Test Stash browsing and preview playback
|
|
```
|
|
|
|
### Before Each Trip
|
|
|
|
**On Netgrimoire:**
|
|
- [ ] Curate new content to Pocket media directory
|
|
- [ ] Scan Stash-Pocket to pick up new files
|
|
- [ ] Generate previews for new content
|
|
- [ ] Verify previews completed: `http://netgrimoire.local:9998`
|
|
- [ ] Manually trigger sync: `sudo systemctl start pocketgrimoire-sync.service`
|
|
- [ ] Wait for sync completion (check logs)
|
|
- [ ] Verify on Pocket: `http://pocket-grimoire.local:9999`
|
|
|
|
**On Pocket Grimoire:**
|
|
- [ ] Test Stash loads and browses correctly
|
|
- [ ] Test preview playback
|
|
- [ ] Test StashApp on Onn boxes connects
|
|
- [ ] Verify media files accessible
|
|
|
|
### After Trips
|
|
|
|
**On Pocket Grimoire:**
|
|
- Check sync logs for any errors during trip
|
|
- No action needed - sync continues automatically
|
|
|
|
**On Netgrimoire:**
|
|
- Review what content was most useful
|
|
- Curate more similar content for next trip
|
|
- Remove old/unwanted content from Pocket directory
|
|
|
|
---
|
|
|
|
## Comparison: Single Dataset vs Two Instances
|
|
|
|
### Why Not Just One Stash Instance?
|
|
|
|
**Option A: Single Stash watching everything (NOT recommended):**
|
|
```
|
|
One Stash instance
|
|
├── Watches all media (home + pocket)
|
|
├── Huge database (slow)
|
|
├── Long scan times
|
|
└── Everything syncs (or nothing does)
|
|
```
|
|
|
|
**Problems:**
|
|
- ❌ Can't sync just travel subset
|
|
- ❌ Full database is massive (slow on Pi)
|
|
- ❌ Scanning entire library takes hours
|
|
- ❌ No clear separation of content
|
|
|
|
**Option B: Two instances (RECOMMENDED - this guide):**
|
|
```
|
|
Stash-Main Stash-Pocket
|
|
├── All media ├── Pocket media only
|
|
├── Large database ├── Small database
|
|
├── Stays on Netgrimoire ├── Syncs to Pocket
|
|
└── Full features └── Read-only on travel
|
|
```
|
|
|
|
**Benefits:**
|
|
- ✅ Clear separation of home vs travel
|
|
- ✅ Smaller Pocket database (faster, lighter)
|
|
- ✅ Only travel data syncs
|
|
- ✅ Independent organization
|
|
- ✅ Preview travel setup before trips
|
|
|
|
---
|
|
|
|
## Summary
|
|
|
|
### What You Get with Two-Instance Stash
|
|
|
|
**At Home (Netgrimoire):**
|
|
- ✅ Stash-Main: Full library management (port 9999)
|
|
- ✅ Stash-Pocket: Travel subset preview (port 9998)
|
|
- ✅ Heavy operations (scanning, previews) on powerful hardware
|
|
- ✅ Independent databases and organizations
|
|
|
|
**On Travel (Pocket Grimoire):**
|
|
- ✅ Stash-Pocket: Full browsing of travel library (port 9999)
|
|
- ✅ All previews and metadata available offline
|
|
- ✅ Zero CPU load (read-only, no generation)
|
|
- ✅ Works with StashApp on Onn boxes
|
|
- ✅ Automatic sync every 6 hours when connected
|
|
|
|
**Storage:**
|
|
- Vault SSD: ~510GB-1.1TB (Stash + media + other data)
|
|
- Fits comfortably on 1-2TB Vault SSD
|
|
- Stash-Main data stays on Netgrimoire (doesn't sync)
|
|
|
|
**Maintenance:**
|
|
- Curate travel content on Netgrimoire
|
|
- Scan and generate previews there
|
|
- Automatic sync handles replication
|
|
- Read-only consumption on travel
|
|
- No manual database management needed
|
|
|
|
---
|
|
|
|
## What This Guide Provides
|
|
|
|
✅ **Two-instance architecture** (Main at home, Pocket for travel)
|
|
✅ **Single sync path** (everything in `/export/vault/Green/Pocket/`)
|
|
✅ **Automatic replication** (existing ZFS sync handles it)
|
|
✅ **Path consistency** (same relative paths on both systems)
|
|
✅ **Read-only travel mode** (browse only, no writes)
|
|
✅ **Complete Docker Compose files** for all three instances
|
|
✅ **No symlinks needed** (media stored directly in Pocket directory)
|
|
✅ **Professional setup** (separation of concerns, clear organization)
|
|
|
|
---
|
|
|
|
*This guide supplements the main Pocket Grimoire deployment guide. Ensure main guide is completed before adding Stash.*
|
|
|
|
---
|
|
|
|
## Architecture
|
|
|
|
```
|
|
┌─────────────────────────────────────────┐
|
|
│ NETGRIMOIRE (Home - Heavy Lifting) │
|
|
├─────────────────────────────────────────┤
|
|
│ Stash Container: │
|
|
│ - Full scanning │
|
|
│ - Preview generation │
|
|
│ - Scene detection │
|
|
│ - Database writes │
|
|
│ - All CPU/GPU intensive work │
|
|
│ │
|
|
│ ZFS Dataset: vault/stash │
|
|
│ - Stash database │
|
|
│ - Generated previews │
|
|
│ - Thumbnails & sprites │
|
|
│ - Scene markers │
|
|
└─────────────────────────────────────────┘
|
|
↓
|
|
ZFS Send/Receive
|
|
(via syncoid every 6 hours)
|
|
↓
|
|
┌─────────────────────────────────────────┐
|
|
│ POCKET GRIMOIRE (Travel - Read Only) │
|
|
├─────────────────────────────────────────┤
|
|
│ Stash Container: │
|
|
│ - Read-only mode │
|
|
│ - No scanning │
|
|
│ - No generation │
|
|
│ - Just browse existing data │
|
|
│ │
|
|
│ ZFS Dataset: vaultpg/stash │
|
|
│ - Mirrored from Netgrimoire │
|
|
│ - Complete database replica │
|
|
│ - All previews pre-generated │
|
|
└─────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## Storage Requirements
|
|
|
|
### On Netgrimoire
|
|
```
|
|
Database: 500MB - 2GB (depends on library size)
|
|
Generated previews: 5GB - 50GB (depends on preview settings)
|
|
Blobs/markers: 1GB - 10GB
|
|
───────────────────────────────────────────────────────
|
|
Total: 6.5GB - 62GB
|
|
```
|
|
|
|
### On Pocket Grimoire
|
|
```
|
|
Same as Netgrimoire (full replica via ZFS)
|
|
Stored on Vault SSD (vaultpg pool)
|
|
```
|
|
|
|
### Sync Bandwidth
|
|
- **Initial sync:** 10-30GB (1-2 hours on gigabit LAN)
|
|
- **Incremental sync:** 50MB - 500MB per 6 hours (2-10 minutes)
|
|
- **After adding 10 videos:** ~210MB (database + previews)
|
|
|
|
---
|
|
|
|
## Resource Impact
|
|
|
|
### Updated Resource Profile (With Stash)
|
|
|
|
**Idle:**
|
|
```
|
|
Wiki.js + PostgreSQL: ~250MB RAM
|
|
Jellyfin (idle): ~150MB RAM
|
|
Stash (read-only): ~200MB RAM # Much lighter than active Stash
|
|
ZFS ARC: ~512MB RAM
|
|
System: ~200MB RAM
|
|
─────────────────────────────────────────
|
|
Total: ~1.3GB / 8GB RAM ✓
|
|
CPU: <10%
|
|
Temperature: Cool
|
|
```
|
|
|
|
**Browsing Stash:**
|
|
```
|
|
Stash (active): ~300MB RAM
|
|
Other services: ~1.1GB RAM
|
|
─────────────────────────────────────────
|
|
Total: ~1.4GB / 8GB RAM ✓
|
|
CPU: <15%
|
|
Temperature: Cool to Warm
|
|
```
|
|
|
|
**Media Playback + Stash Browsing:**
|
|
```
|
|
Jellyfin (serving): ~200MB RAM
|
|
Stash (active): ~300MB RAM
|
|
Wiki.js + PostgreSQL: ~250MB RAM
|
|
ZFS ARC: ~512MB RAM
|
|
System: ~200MB RAM
|
|
─────────────────────────────────────────
|
|
Total: ~1.5GB / 8GB RAM ✓
|
|
Still plenty of headroom
|
|
```
|
|
|
|
---
|
|
|
|
## Installation: Netgrimoire (Home)
|
|
|
|
### 1. Create ZFS Datasets
|
|
|
|
```bash
|
|
# On Netgrimoire
|
|
sudo zfs create -o recordsize=16K vault/stash
|
|
sudo zfs create -o recordsize=16K vault/stash/config # Database
|
|
sudo zfs create -o recordsize=1M vault/stash/generated # Previews
|
|
sudo zfs create -o recordsize=128K vault/stash/blobs # Scene markers
|
|
sudo zfs create vault/stash/cache # Temporary (won't replicate)
|
|
|
|
# Set appropriate permissions
|
|
sudo chown -R 1000:1000 /vault/stash
|
|
```
|
|
|
|
**Why different recordsizes:**
|
|
- **16K** for config (SQLite database performs best with small records)
|
|
- **1M** for generated (large video preview files)
|
|
- **128K** for blobs (medium-sized screenshots and markers)
|
|
|
|
### 2. Create Stash Docker Compose
|
|
|
|
```bash
|
|
mkdir -p /srv/netgrimoire/stacks/stash
|
|
nano /srv/netgrimoire/stacks/stash/docker-compose.yml
|
|
```
|
|
|
|
```yaml
|
|
services:
|
|
stash:
|
|
image: stashapp/stash:latest
|
|
container_name: netgrimoire_stash
|
|
environment:
|
|
- STASH_STASH=/data/
|
|
- STASH_GENERATED=/generated/
|
|
- STASH_CACHE=/cache/
|
|
- STASH_BLOBS=/blobs/
|
|
- TZ=America/Chicago
|
|
volumes:
|
|
- /vault/stash/config:/root/.stash
|
|
- /vault/stash/generated:/generated
|
|
- /vault/stash/cache:/cache
|
|
- /vault/stash/blobs:/blobs
|
|
- /vault/media:/data:ro # Your media library (read-only)
|
|
ports:
|
|
- "9999:9999"
|
|
restart: unless-stopped
|
|
```
|
|
|
|
**Start Stash:**
|
|
```bash
|
|
cd /srv/netgrimoire/stacks/stash
|
|
docker compose up -d
|
|
```
|
|
|
|
### 3. Configure Stash
|
|
|
|
1. **Access Stash:**
|
|
- Open browser: `http://netgrimoire.local:9999`
|
|
- Complete initial setup wizard
|
|
|
|
2. **Add Library:**
|
|
- Settings → Library
|
|
- Add folder: `/data/library/movies` (or your media path)
|
|
- Save
|
|
|
|
3. **Configure Previews:**
|
|
- Settings → Tasks → Generate
|
|
- Preview Generation: Enable
|
|
- Preview Settings:
|
|
- Video encoding: VP9 or H.264
|
|
- Resolution: 720p (good quality, reasonable size)
|
|
- Segment duration: 10 seconds
|
|
- Generate image previews: Enable
|
|
- Generate sprites: Enable
|
|
|
|
4. **Run Initial Scan:**
|
|
- Tasks → Scan
|
|
- Wait for completion (can take hours depending on library size)
|
|
|
|
5. **Generate Previews:**
|
|
- Tasks → Generate → Generate Previews
|
|
- This is CPU intensive - let run at home
|
|
- Can take many hours depending on library size
|
|
|
|
6. **Optional: Scene Detection:**
|
|
- Tasks → Generate → Auto Tag
|
|
- Scene detection, performer matching, etc.
|
|
- Very CPU intensive, run at home only
|
|
|
|
### 4. Take ZFS Snapshots (Optional but Recommended)
|
|
|
|
```bash
|
|
# After initial scan and preview generation
|
|
sudo zfs snapshot vault/stash/config@initial
|
|
sudo zfs snapshot vault/stash/generated@initial
|
|
sudo zfs snapshot vault/stash/blobs@initial
|
|
```
|
|
|
|
---
|
|
|
|
## Installation: Pocket Grimoire (Travel)
|
|
|
|
### 1. Create ZFS Datasets
|
|
|
|
```bash
|
|
# On Pocket Grimoire
|
|
sudo zfs create -o recordsize=16K vaultpg/stash
|
|
sudo zfs create -o recordsize=16K vaultpg/stash/config
|
|
sudo zfs create -o recordsize=1M vaultpg/stash/generated
|
|
sudo zfs create -o recordsize=128K vaultpg/stash/blobs
|
|
sudo zfs create vaultpg/stash/cache # Local cache only, not synced
|
|
|
|
# Set permissions
|
|
sudo chown -R 1000:1000 /srv/vaultpg/stash
|
|
```
|
|
|
|
### 2. Create Stash Docker Compose (Read-Only)
|
|
|
|
```bash
|
|
mkdir -p /srv/pocket-grimoire/stacks/stash
|
|
nano /srv/pocket-grimoire/stacks/stash/docker-compose.yml
|
|
```
|
|
|
|
```yaml
|
|
services:
|
|
stash:
|
|
image: stashapp/stash:latest
|
|
container_name: pocketgrimoire_stash
|
|
environment:
|
|
- STASH_STASH=/data/
|
|
- STASH_GENERATED=/generated/
|
|
- STASH_CACHE=/cache/
|
|
- STASH_BLOBS=/blobs/
|
|
- TZ=America/Chicago
|
|
volumes:
|
|
- /srv/vaultpg/stash/config:/root/.stash:ro # READ-ONLY
|
|
- /srv/vaultpg/stash/generated:/generated:ro # READ-ONLY
|
|
- /srv/vaultpg/stash/blobs:/blobs:ro # READ-ONLY
|
|
- /srv/pocket-grimoire/data/stash/cache:/cache # Local cache (writable)
|
|
- /srv/mediapg:/data:ro # Media (already present, read-only)
|
|
ports:
|
|
- "9999:9999"
|
|
restart: unless-stopped
|
|
```
|
|
|
|
**Note the `:ro` flags** - Filesystem is mounted read-only, preventing any writes.
|
|
|
|
**Start Stash:**
|
|
```bash
|
|
cd /srv/pocket-grimoire/stacks/stash
|
|
docker compose up -d
|
|
```
|
|
|
|
### 3. Configure Stash for Read-Only Operation
|
|
|
|
**After first start:**
|
|
|
|
1. **Access Stash:**
|
|
- Open browser: `http://pocket-grimoire.local:9999`
|
|
- Should show library from Netgrimoire (after first sync)
|
|
|
|
2. **Disable Background Tasks:**
|
|
- Settings → Tasks
|
|
- Disable all automatic tasks:
|
|
- ❌ Auto-scan
|
|
- ❌ Auto-tag
|
|
- ❌ Auto-preview generation
|
|
- ❌ Auto-cleanup
|
|
|
|
3. **Verify Read-Only:**
|
|
- Try to edit a scene or performer
|
|
- Should fail with permission error
|
|
- This confirms read-only mode working
|
|
|
|
---
|
|
|
|
## ZFS Replication Configuration
|
|
|
|
### Update Sync Script
|
|
|
|
Edit your existing sync script to include Stash datasets:
|
|
|
|
```bash
|
|
sudo nano /usr/local/sbin/pocketgrimoire-zfs-pull.sh
|
|
```
|
|
|
|
Add these lines:
|
|
|
|
```bash
|
|
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
SRC_HOST="netgrimoire.local"
|
|
SSH_KEY="/srv/pocket-grimoire/keys/zfs_pull_ro"
|
|
|
|
# Existing vault data syncs...
|
|
syncoid --no-sync-snap --recursive \
|
|
--sshkey "${SSH_KEY}" \
|
|
"root@${SRC_HOST}:vault/docs" \
|
|
"vaultpg/mirror/docs"
|
|
|
|
syncoid --no-sync-snap --recursive \
|
|
--sshkey "${SSH_KEY}" \
|
|
"root@${SRC_HOST}:vault/photos" \
|
|
"vaultpg/mirror/photos"
|
|
|
|
# NEW: Stash database and generated content
|
|
syncoid --no-sync-snap \
|
|
--sshkey "${SSH_KEY}" \
|
|
"root@${SRC_HOST}:vault/stash/config" \
|
|
"vaultpg/stash/config"
|
|
|
|
syncoid --no-sync-snap \
|
|
--sshkey "${SSH_KEY}" \
|
|
"root@${SRC_HOST}:vault/stash/generated" \
|
|
"vaultpg/stash/generated"
|
|
|
|
syncoid --no-sync-snap \
|
|
--sshkey "${SSH_KEY}" \
|
|
"root@${SRC_HOST}:vault/stash/blobs" \
|
|
"vaultpg/stash/blobs"
|
|
|
|
# Note: We skip cache dataset (temporary data, not needed on Pocket)
|
|
```
|
|
|
|
**Sync runs automatically every 6 hours** via existing systemd timer.
|
|
|
|
### Manual Sync (For Testing)
|
|
|
|
```bash
|
|
# Trigger sync immediately
|
|
sudo systemctl start pocketgrimoire-sync.service
|
|
|
|
# Watch progress
|
|
tail -f /var/log/pocketgrimoire-sync.log
|
|
|
|
# Verify Stash data synced
|
|
ls -lh /srv/vaultpg/stash/config
|
|
ls -lh /srv/vaultpg/stash/generated
|
|
```
|
|
|
|
---
|
|
|
|
## Media Path Consistency
|
|
|
|
**Critical:** Media paths must be consistent between Netgrimoire and Pocket Grimoire.
|
|
|
|
### Option 1: Matching Paths
|
|
|
|
**If your media is in same location:**
|
|
```
|
|
Netgrimoire: /vault/media/library/
|
|
Pocket: /srv/mediapg/library/
|
|
```
|
|
|
|
**Stash stores absolute paths** - ensure they match or use symlinks.
|
|
|
|
### Option 2: Symlinks
|
|
|
|
```bash
|
|
# On Pocket Grimoire
|
|
sudo ln -s /srv/mediapg /vault/media
|
|
```
|
|
|
|
This makes `/vault/media` point to `/srv/mediapg`, matching Netgrimoire's paths.
|
|
|
|
### Option 3: Stash Path Mapping (If Stash supports it)
|
|
|
|
Some versions of Stash support path mapping in config. Check Stash documentation.
|
|
|
|
---
|
|
|
|
## Workflow
|
|
|
|
### At Home (Before Trips)
|
|
|
|
**On Netgrimoire:**
|
|
1. Add new media to library
|
|
2. Stash auto-scans (or trigger manually)
|
|
3. Previews generate automatically (or trigger manually)
|
|
4. Tag/organize content as desired
|
|
5. Everything happens in background
|
|
|
|
**Pocket Grimoire (automatic):**
|
|
1. Every 6 hours: syncoid pulls changes from Netgrimoire
|
|
2. Stash database updated
|
|
3. New previews synced
|
|
4. Scene markers updated
|
|
5. Ready for next trip - no manual intervention
|
|
|
|
### While Traveling
|
|
|
|
**On Pocket Grimoire:**
|
|
1. Access Stash: `http://pocket-grimoire.local:9999`
|
|
2. Browse library, tags, performers, studios
|
|
3. View previews and scene markers
|
|
4. Click to play via Jellyfin or external player
|
|
5. **Cannot:** Scan, edit tags, generate previews (read-only)
|
|
|
|
**If you need to edit:**
|
|
1. VPN back to Netgrimoire (via WireGuard)
|
|
2. Access Netgrimoire Stash: `http://netgrimoire.local:9999`
|
|
3. Make changes there
|
|
4. Changes sync on next 6-hour cycle
|
|
|
|
### After Returning Home
|
|
|
|
1. Sync happens automatically
|
|
2. Any changes made on Netgrimoire while away are pulled
|
|
3. Pocket Grimoire stays up-to-date
|
|
4. No manual intervention required
|
|
|
|
---
|
|
|
|
## Accessing Stash
|
|
|
|
### From Onn Streaming Boxes
|
|
|
|
**Install StashApp for Android TV:**
|
|
- See "Onn 4K Streaming Box Setup Guide" for detailed instructions
|
|
- Download APK from: https://github.com/damontecres/StashAppAndroidTV/releases
|
|
- Sideload onto Onn boxes
|
|
- Configure server: `http://pocket-grimoire.local:9999`
|
|
|
|
### From Laptop
|
|
|
|
**Via Web Browser:**
|
|
- Open: `http://pocket-grimoire.local:9999`
|
|
- Full Stash web interface available
|
|
- Same as Netgrimoire, but read-only
|
|
|
|
### From Phone/Tablet
|
|
|
|
**Via Web Browser:**
|
|
- Connect to portapotty WiFi
|
|
- Open: `http://pocket-grimoire.local:9999`
|
|
- Mobile-responsive interface
|
|
|
|
---
|
|
|
|
## Updated Service Access Summary
|
|
|
|
**When connected to portapotty network:**
|
|
|
|
```
|
|
Wiki.js: http://pocket-grimoire.local:3000
|
|
Jellyfin: http://pocket-grimoire.local:8096
|
|
Stash: http://pocket-grimoire.local:9999 ← NEW
|
|
File Browser: http://pocket-grimoire.local:8080
|
|
Dozzle: http://pocket-grimoire.local:8888
|
|
SSH: ssh user@pocket-grimoire.local
|
|
NFS Media: nfs://pocket-grimoire.local/srv/mediapg
|
|
Router Admin: http://192.168.8.1
|
|
```
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
### Stash Won't Start
|
|
|
|
**Check Docker container status:**
|
|
```bash
|
|
docker ps | grep stash
|
|
docker logs pocketgrimoire_stash
|
|
```
|
|
|
|
**Common issues:**
|
|
- ZFS datasets not mounted: `zfs mount -a`
|
|
- Permission denied: `sudo chown -R 1000:1000 /srv/vaultpg/stash`
|
|
- Port conflict: Another service using port 9999
|
|
|
|
### Stash Shows "Database is locked"
|
|
|
|
**This means read-only mode is working correctly.**
|
|
|
|
If you need to make changes:
|
|
1. VPN to Netgrimoire
|
|
2. Edit on Netgrimoire Stash
|
|
3. Changes sync to Pocket on next cycle
|
|
|
|
### Previews Not Showing
|
|
|
|
**Verify previews synced:**
|
|
```bash
|
|
ls /srv/vaultpg/stash/generated/
|
|
# Should show many .webp or .mp4 files
|
|
```
|
|
|
|
**If empty:**
|
|
- Previews not generated on Netgrimoire yet
|
|
- Sync hasn't completed (check sync logs)
|
|
- Check: `tail -n 200 /var/log/pocketgrimoire-sync.log`
|
|
|
|
### Media Files Not Found
|
|
|
|
**Check paths match:**
|
|
```bash
|
|
# On Netgrimoire, Stash sees files at:
|
|
# /vault/media/library/movies/
|
|
|
|
# On Pocket, files are at:
|
|
# /srv/mediapg/library/movies/
|
|
|
|
# Create symlink to match:
|
|
sudo ln -s /srv/mediapg /vault/media
|
|
```
|
|
|
|
**Or verify Docker volume mount:**
|
|
```bash
|
|
docker inspect pocketgrimoire_stash | grep -A 10 Mounts
|
|
# Should show /srv/mediapg mounted as /data
|
|
```
|
|
|
|
### Sync Takes Too Long
|
|
|
|
**Check what's being synced:**
|
|
```bash
|
|
# Watch sync in progress
|
|
sudo zfs list -t snapshot | grep stash
|
|
|
|
# Check dataset sizes
|
|
sudo zfs list | grep stash
|
|
```
|
|
|
|
**Optimization:**
|
|
- Reduce preview quality on Netgrimoire (smaller files)
|
|
- Sync less frequently (change timer from 6h to 12h)
|
|
- Only sync when on fast network (manual trigger)
|
|
|
|
### Stash API Key Issues
|
|
|
|
**If StashApp asks for API key:**
|
|
|
|
1. **Find API key on Netgrimoire:**
|
|
```bash
|
|
# On Netgrimoire
|
|
cat /vault/stash/config/config.yml | grep api_key
|
|
```
|
|
|
|
2. **Or via Stash web UI:**
|
|
- Settings → Security → API Key
|
|
- Generate key if not present
|
|
- Copy key
|
|
|
|
3. **Configure StashApp:**
|
|
- Settings → Server → API Key
|
|
- Paste key from Netgrimoire
|
|
|
|
**Note:** API key is in config, which syncs to Pocket, so should be the same.
|
|
|
|
---
|
|
|
|
## Optimization Tips
|
|
|
|
### Reduce Storage Usage
|
|
|
|
**On Netgrimoire (affects Pocket via sync):**
|
|
|
|
1. **Lower preview quality:**
|
|
- Settings → Tasks → Generate
|
|
- Video resolution: 480p instead of 720p
|
|
- Lower bitrate
|
|
- Smaller file sizes = faster sync
|
|
|
|
2. **Disable sprite generation:**
|
|
- Settings → Tasks → Generate
|
|
- Disable sprite generation (just use video previews)
|
|
- Saves significant space
|
|
|
|
3. **Limit preview duration:**
|
|
- Settings → Tasks → Generate
|
|
- Preview duration: 20 seconds instead of 60 seconds
|
|
- Smaller files
|
|
|
|
### Speed Up Sync
|
|
|
|
**Initial sync optimization:**
|
|
```bash
|
|
# First sync: Compress during transfer
|
|
syncoid --compress=lz4 \
|
|
--sshkey "${SSH_KEY}" \
|
|
"root@${SRC_HOST}:vault/stash/generated" \
|
|
"vaultpg/stash/generated"
|
|
```
|
|
|
|
**Bandwidth limiting (if needed):**
|
|
```bash
|
|
# Limit to 10MB/s
|
|
syncoid --bwlimit=10M \
|
|
--sshkey "${SSH_KEY}" \
|
|
"root@${SRC_HOST}:vault/stash/config" \
|
|
"vaultpg/stash/config"
|
|
```
|
|
|
|
### Reduce Preview Generation Load
|
|
|
|
**On Netgrimoire:**
|
|
- Generate previews during off-hours (nightly)
|
|
- Use Task Scheduler in Stash
|
|
- Limit concurrent preview generation
|
|
- Lower thread count for generation
|
|
|
|
---
|
|
|
|
## Maintenance
|
|
|
|
### Weekly
|
|
|
|
**On Netgrimoire:**
|
|
- Check Stash is running: `docker ps | grep stash`
|
|
- Verify previews generating (if auto-enabled)
|
|
- Check disk usage: `zfs list | grep stash`
|
|
|
|
**On Pocket Grimoire:**
|
|
- Verify sync is working: `tail /var/log/pocketgrimoire-sync.log`
|
|
- Check Stash is accessible: `http://pocket-grimoire.local:9999`
|
|
|
|
### Monthly
|
|
|
|
**On Netgrimoire:**
|
|
- Run manual scan if auto-scan disabled
|
|
- Clean up orphaned files: Tasks → Clean
|
|
- Check database integrity: Tasks → Optimize Database
|
|
- ZFS scrub: `sudo zfs scrub vault/stash`
|
|
|
|
**On Pocket Grimoire:**
|
|
- Verify dataset health: `sudo zpool status vaultpg`
|
|
- Check sync logs for errors
|
|
- Test Stash browsing and preview playback
|
|
|
|
### Before Trips
|
|
|
|
- [ ] Run scan on Netgrimoire (capture new content)
|
|
- [ ] Generate previews for new content
|
|
- [ ] Verify sync completed successfully
|
|
- [ ] Test Stash on Pocket Grimoire
|
|
- [ ] Verify StashApp on Onn boxes connects
|
|
|
|
### After Trips
|
|
|
|
- Check sync logs for any errors during trip
|
|
- No action needed - sync continues automatically
|
|
|
|
---
|
|
|
|
## Alternative: Manual Database Export (Not Recommended)
|
|
|
|
**If ZFS replication is not available:**
|
|
|
|
You can manually export/import Stash database:
|
|
|
|
```bash
|
|
# On Netgrimoire - Export
|
|
sqlite3 /vault/stash/config/stash-go.sqlite ".backup /tmp/stash-backup.db"
|
|
scp /tmp/stash-backup.db pocket-grimoire:/tmp/
|
|
|
|
# On Pocket Grimoire - Import
|
|
docker compose down
|
|
cp /tmp/stash-backup.db /srv/vaultpg/stash/config/stash-go.sqlite
|
|
docker compose up -d
|
|
```
|
|
|
|
**Why this is not recommended:**
|
|
- Manual process (error-prone)
|
|
- Doesn't sync previews/blobs automatically
|
|
- Must copy those separately (tens of GB)
|
|
- ZFS replication is much cleaner
|
|
|
|
---
|
|
|
|
## Summary
|
|
|
|
**What you get with Stash on Pocket Grimoire:**
|
|
- ✅ Full Stash browsing offline
|
|
- ✅ All previews and metadata available
|
|
- ✅ Zero CPU load on Pi (read-only)
|
|
- ✅ Automatic synchronization
|
|
- ✅ Professional media library management
|
|
- ✅ Scene markers and performer tagging
|
|
- ✅ Works with StashApp on Onn boxes
|
|
|
|
**What you give up:**
|
|
- ❌ Cannot edit/tag while traveling (must VPN to Netgrimoire)
|
|
- ❌ Cannot generate previews on travel (shouldn't anyway)
|
|
- ❌ 10-30GB additional storage on Vault SSD
|
|
- ❌ Slightly more complex setup (but worth it)
|
|
|
|
**Recommended for:**
|
|
- Large media libraries that need organization
|
|
- Users who want professional media management
|
|
- Those who already use or want to use Stash
|
|
- Anyone who values rich metadata and previews
|
|
|
|
**Skip if:**
|
|
- Just want simple media playback (Jellyfin is enough)
|
|
- Very limited storage on Vault SSD
|
|
- Don't want complexity of ZFS replication
|
|
- Don't need tagging/scene detection features
|
|
|
|
---
|
|
|
|
*This guide supplements the main Pocket Grimoire deployment guide. Ensure main guide is completed before adding Stash.*
|