docs: update Netgrimoire/Pocket/Deployment_Guide
This commit is contained in:
parent
513b1e729b
commit
9327335fb8
1 changed files with 626 additions and 88 deletions
|
|
@ -2,7 +2,7 @@
|
||||||
title: Pocket Grimoire
|
title: Pocket Grimoire
|
||||||
description:
|
description:
|
||||||
published: true
|
published: true
|
||||||
date: 2026-02-20T04:54:31.450Z
|
date: 2026-02-21T04:25:58.904Z
|
||||||
tags:
|
tags:
|
||||||
editor: markdown
|
editor: markdown
|
||||||
dateCreated: 2026-02-20T04:41:35.122Z
|
dateCreated: 2026-02-20T04:41:35.122Z
|
||||||
|
|
@ -502,35 +502,33 @@ sudo apt install -y zfsutils-linux
|
||||||
sudo zpool list
|
sudo zpool list
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4. Configure ZFS Pools
|
### 4. Initial Drive Setup on Netgrimoire (Before Moving to Pocket)
|
||||||
|
|
||||||
**Important:** Replace `/dev/sdX` with your actual device identifiers. Use `lsblk` to identify drives.
|
**IMPORTANT: Build drives on Netgrimoire first, then move to Pocket Grimoire.**
|
||||||
|
|
||||||
**Create Vault Pool (Always Connected):**
|
This approach allows you to:
|
||||||
|
- Create encrypted pools with proper passphrases
|
||||||
|
- Perform initial ZFS sync while drives are fast-connected (SATA/USB 3.0)
|
||||||
|
- Verify data integrity before moving drives
|
||||||
|
- Test encryption/unlock on powerful hardware first
|
||||||
|
|
||||||
|
#### On Netgrimoire: Create and Populate Drives
|
||||||
|
|
||||||
|
**Connect drives to Netgrimoire:**
|
||||||
|
- VAULT SSD (1-2TB) via USB 3.0 or SATA
|
||||||
|
- MEDIA-PERSONAL SSD (2TB+) via USB 3.0 or SATA
|
||||||
|
- MEDIA-FAMILY SSD (2TB+) via USB 3.0 or SATA (optional, can be created later)
|
||||||
|
|
||||||
|
**Identify drives:**
|
||||||
```bash
|
```bash
|
||||||
# Identify Vault SSD
|
# On Netgrimoire
|
||||||
lsblk
|
lsblk
|
||||||
|
# Note device names: /dev/sdX, /dev/sdY, /dev/sdZ
|
||||||
# Create encrypted ZFS pool
|
|
||||||
sudo zpool create -o ashift=12 \
|
|
||||||
-O encryption=on \
|
|
||||||
-O keylocation=prompt \
|
|
||||||
-O keyformat=passphrase \
|
|
||||||
-O compression=lz4 \
|
|
||||||
-O atime=off \
|
|
||||||
-O recordsize=1M \
|
|
||||||
-m /srv/vaultpg \
|
|
||||||
vaultpg /dev/sdX
|
|
||||||
|
|
||||||
# Create datasets
|
|
||||||
sudo zfs create -o recordsize=16K vaultpg/wiki-pg # PostgreSQL
|
|
||||||
sudo zfs create vaultpg/repos # Git repos
|
|
||||||
sudo zfs create vaultpg/pocket-grimoire # App data
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Create Media Pool (Rotated):**
|
**Create VAULT pool (encrypted):**
|
||||||
```bash
|
```bash
|
||||||
# For Personal Media SSD
|
# On Netgrimoire
|
||||||
sudo zpool create -o ashift=12 \
|
sudo zpool create -o ashift=12 \
|
||||||
-O encryption=on \
|
-O encryption=on \
|
||||||
-O keylocation=prompt \
|
-O keylocation=prompt \
|
||||||
|
|
@ -538,23 +536,184 @@ sudo zpool create -o ashift=12 \
|
||||||
-O compression=lz4 \
|
-O compression=lz4 \
|
||||||
-O atime=off \
|
-O atime=off \
|
||||||
-O recordsize=1M \
|
-O recordsize=1M \
|
||||||
-m /srv/mediapg \
|
-m /mnt/pocket-vault \
|
||||||
mediapg /dev/sdY
|
pocket-vault /dev/sdX
|
||||||
|
|
||||||
sudo zfs create mediapg/library
|
# Enter STRONG passphrase when prompted
|
||||||
sudo zfs create mediapg/library/movies
|
# Write down this passphrase - you'll need it on Pocket Grimoire
|
||||||
sudo zfs create mediapg/library/tv
|
|
||||||
|
|
||||||
# For Family Media SSD (unencrypted)
|
# Create datasets matching Pocket structure
|
||||||
# When swapping drives:
|
sudo zfs create -o recordsize=16K pocket-vault/wiki-pg
|
||||||
sudo zpool export mediapg
|
sudo zfs create pocket-vault/repos
|
||||||
# Connect family SSD
|
sudo zfs create pocket-vault/pocket-grimoire
|
||||||
|
sudo zfs create pocket-vault/Green
|
||||||
|
sudo zfs create pocket-vault/Green/Pocket
|
||||||
|
sudo zfs create pocket-vault/Green/Pocket/stash
|
||||||
|
sudo zfs create pocket-vault/Green/Pocket/media
|
||||||
|
sudo zfs create pocket-vault/veracrypt-containers
|
||||||
|
|
||||||
|
# Set ownership
|
||||||
|
sudo chown -R 1000:1000 /mnt/pocket-vault
|
||||||
|
```
|
||||||
|
|
||||||
|
**Create MEDIA-PERSONAL pool (encrypted):**
|
||||||
|
```bash
|
||||||
|
# On Netgrimoire
|
||||||
|
sudo zpool create -o ashift=12 \
|
||||||
|
-O encryption=on \
|
||||||
|
-O keylocation=prompt \
|
||||||
|
-O keyformat=passphrase \
|
||||||
|
-O compression=lz4 \
|
||||||
|
-O atime=off \
|
||||||
|
-O recordsize=1M \
|
||||||
|
-m /mnt/pocket-media-personal \
|
||||||
|
pocket-media-personal /dev/sdY
|
||||||
|
|
||||||
|
# Enter STRONG passphrase (can be different from VAULT)
|
||||||
|
# Write down this passphrase
|
||||||
|
|
||||||
|
# Create datasets
|
||||||
|
sudo zfs create pocket-media-personal/library
|
||||||
|
sudo zfs create pocket-media-personal/library/movies
|
||||||
|
sudo zfs create pocket-media-personal/library/tv
|
||||||
|
|
||||||
|
# Set ownership
|
||||||
|
sudo chown -R 1000:1000 /mnt/pocket-media-personal
|
||||||
|
```
|
||||||
|
|
||||||
|
**Create MEDIA-FAMILY pool (unencrypted, optional now or later):**
|
||||||
|
```bash
|
||||||
|
# On Netgrimoire
|
||||||
sudo zpool create -o ashift=12 \
|
sudo zpool create -o ashift=12 \
|
||||||
-O compression=lz4 \
|
-O compression=lz4 \
|
||||||
-O atime=off \
|
-O atime=off \
|
||||||
-O recordsize=1M \
|
-O recordsize=1M \
|
||||||
-m /srv/mediapg \
|
-m /mnt/pocket-media-family \
|
||||||
mediapg /dev/sdY
|
pocket-media-family /dev/sdZ
|
||||||
|
|
||||||
|
# No encryption - family can use this drive on any system
|
||||||
|
|
||||||
|
# Create datasets
|
||||||
|
sudo zfs create pocket-media-family/library
|
||||||
|
sudo zfs create pocket-media-family/library/movies
|
||||||
|
sudo zfs create pocket-media-family/library/tv
|
||||||
|
|
||||||
|
# Set ownership
|
||||||
|
sudo chown -R 1000:1000 /mnt/pocket-media-family
|
||||||
|
```
|
||||||
|
|
||||||
|
**Perform initial sync to VAULT:**
|
||||||
|
```bash
|
||||||
|
# On Netgrimoire
|
||||||
|
# Sync data from Netgrimoire to Pocket VAULT drive
|
||||||
|
|
||||||
|
# Sync Pocket directory structure
|
||||||
|
sudo rsync -avP --exclude='cache' \
|
||||||
|
/export/vault/Green/Pocket/ \
|
||||||
|
/mnt/pocket-vault/Green/Pocket/
|
||||||
|
|
||||||
|
# Or use ZFS send/receive for atomic snapshot
|
||||||
|
sudo zfs snapshot vault/Green/Pocket@initial
|
||||||
|
sudo zfs send vault/Green/Pocket@initial | \
|
||||||
|
sudo zfs receive pocket-vault/Green/Pocket
|
||||||
|
|
||||||
|
# Verify data
|
||||||
|
ls -lh /mnt/pocket-vault/Green/Pocket/
|
||||||
|
du -sh /mnt/pocket-vault/Green/Pocket/
|
||||||
|
```
|
||||||
|
|
||||||
|
**Populate MEDIA-PERSONAL (optional - curate content):**
|
||||||
|
```bash
|
||||||
|
# On Netgrimoire
|
||||||
|
# Copy curated personal media to Pocket media drive
|
||||||
|
|
||||||
|
# Example: Copy favorite movies
|
||||||
|
sudo cp /export/vault/media/library/movies/favorites/*.mp4 \
|
||||||
|
/mnt/pocket-media-personal/library/movies/
|
||||||
|
|
||||||
|
# Or use rsync for large transfers
|
||||||
|
sudo rsync -avP \
|
||||||
|
/export/vault/media/library/tv/FavoriteShow/ \
|
||||||
|
/mnt/pocket-media-personal/library/tv/FavoriteShow/
|
||||||
|
|
||||||
|
# Verify
|
||||||
|
du -sh /mnt/pocket-media-personal/library/
|
||||||
|
```
|
||||||
|
|
||||||
|
**Export pools before disconnecting:**
|
||||||
|
```bash
|
||||||
|
# On Netgrimoire
|
||||||
|
# CRITICAL: Export pools before physically disconnecting drives
|
||||||
|
|
||||||
|
sudo zpool export pocket-vault
|
||||||
|
sudo zpool export pocket-media-personal
|
||||||
|
sudo zpool export pocket-media-family # if created
|
||||||
|
|
||||||
|
# Verify exported
|
||||||
|
zpool list
|
||||||
|
# Should NOT show pocket-* pools
|
||||||
|
```
|
||||||
|
|
||||||
|
**Physically disconnect drives from Netgrimoire.**
|
||||||
|
|
||||||
|
### 5. Configure ZFS Pools on Pocket Grimoire
|
||||||
|
|
||||||
|
**Now connect drives to Pocket Grimoire:**
|
||||||
|
- VAULT → Anker USB-A port #2
|
||||||
|
- MEDIA-PERSONAL or MEDIA-FAMILY → Raspberry Pi USB 3.0 port
|
||||||
|
|
||||||
|
**Import and rename pools:**
|
||||||
|
```bash
|
||||||
|
# On Pocket Grimoire (SSH into Pi)
|
||||||
|
ssh user@pocket-grimoire.local
|
||||||
|
|
||||||
|
# Import VAULT pool with new name
|
||||||
|
sudo zpool import pocket-vault vaultpg
|
||||||
|
|
||||||
|
# Import MEDIA pool with new name
|
||||||
|
sudo zpool import pocket-media-personal mediapg
|
||||||
|
# Or:
|
||||||
|
# sudo zpool import pocket-media-family mediapg
|
||||||
|
|
||||||
|
# Verify pools imported
|
||||||
|
zpool list
|
||||||
|
# Should show: vaultpg, mediapg
|
||||||
|
```
|
||||||
|
|
||||||
|
**Set mount points for Pocket Grimoire:**
|
||||||
|
```bash
|
||||||
|
# Set proper mount points
|
||||||
|
sudo zfs set mountpoint=/srv/vaultpg vaultpg
|
||||||
|
sudo zfs set mountpoint=/srv/mediapg mediapg
|
||||||
|
|
||||||
|
# Create mount points
|
||||||
|
sudo mkdir -p /srv/vaultpg
|
||||||
|
sudo mkdir -p /srv/mediapg
|
||||||
|
|
||||||
|
# Unmount and remount with new paths
|
||||||
|
sudo zfs unmount -a
|
||||||
|
sudo zfs mount -a
|
||||||
|
|
||||||
|
# Verify mounted
|
||||||
|
df -h | grep srv
|
||||||
|
# Should show:
|
||||||
|
# vaultpg mounted on /srv/vaultpg
|
||||||
|
# mediapg mounted on /srv/mediapg
|
||||||
|
|
||||||
|
# Verify data
|
||||||
|
ls /srv/vaultpg/Green/Pocket/
|
||||||
|
ls /srv/mediapg/library/
|
||||||
|
```
|
||||||
|
|
||||||
|
**Configure for headless unlock:**
|
||||||
|
```bash
|
||||||
|
# Set pools to NOT auto-mount on boot
|
||||||
|
# This prevents boot hanging waiting for passphrase
|
||||||
|
|
||||||
|
sudo zfs set canmount=noauto vaultpg
|
||||||
|
sudo zfs set canmount=noauto mediapg
|
||||||
|
|
||||||
|
# Pools will need manual unlock via SSH after boot
|
||||||
```
|
```
|
||||||
|
|
||||||
**Cap ZFS ARC Memory:**
|
**Cap ZFS ARC Memory:**
|
||||||
|
|
@ -565,10 +724,248 @@ sudo nano /etc/modprobe.d/zfs.conf
|
||||||
# Add this line (for 8GB Pi, cap at 1GB):
|
# Add this line (for 8GB Pi, cap at 1GB):
|
||||||
options zfs zfs_arc_max=1073741824
|
options zfs zfs_arc_max=1073741824
|
||||||
|
|
||||||
# Reboot to apply
|
# Save and apply
|
||||||
|
sudo update-initramfs -u
|
||||||
sudo reboot
|
sudo reboot
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 6. Create Headless Unlock Script
|
||||||
|
|
||||||
|
**After reboot, SSH back in and create unlock script:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo nano /usr/local/sbin/unlock-pocket-grimoire.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
# Unlock Pocket Grimoire encrypted ZFS pools (headless operation)
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=========================================="
|
||||||
|
echo " Pocket Grimoire ZFS Unlock (Headless)"
|
||||||
|
echo "=========================================="
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Check if pools are already unlocked
|
||||||
|
if zfs list vaultpg &>/dev/null && mount | grep -q /srv/vaultpg; then
|
||||||
|
echo "✓ vaultpg already unlocked and mounted"
|
||||||
|
else
|
||||||
|
# Import pool if needed
|
||||||
|
if ! zpool list vaultpg &>/dev/null; then
|
||||||
|
echo "Importing vaultpg pool..."
|
||||||
|
sudo zpool import vaultpg
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Unlock Vault pool
|
||||||
|
echo "Unlocking vaultpg (VAULT SSD)..."
|
||||||
|
sudo zfs load-key vaultpg
|
||||||
|
|
||||||
|
# Mount all vaultpg datasets
|
||||||
|
sudo zfs mount vaultpg
|
||||||
|
sudo zfs mount -a
|
||||||
|
|
||||||
|
if mount | grep -q /srv/vaultpg; then
|
||||||
|
echo "✓ vaultpg unlocked and mounted at /srv/vaultpg"
|
||||||
|
else
|
||||||
|
echo "✗ Failed to mount vaultpg"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Check if media pool is present and unlock
|
||||||
|
if zpool list mediapg &>/dev/null; then
|
||||||
|
if zfs list mediapg &>/dev/null && mount | grep -q /srv/mediapg; then
|
||||||
|
echo "✓ mediapg already unlocked and mounted"
|
||||||
|
else
|
||||||
|
echo "Unlocking mediapg (MEDIA-PERSONAL or MEDIA-FAMILY)..."
|
||||||
|
|
||||||
|
# Check if encrypted (MEDIA-PERSONAL) or not (MEDIA-FAMILY)
|
||||||
|
if zfs get encryption mediapg | grep -q "encryption.*on"; then
|
||||||
|
sudo zfs load-key mediapg
|
||||||
|
fi
|
||||||
|
|
||||||
|
sudo zfs mount mediapg
|
||||||
|
sudo zfs mount -a
|
||||||
|
|
||||||
|
if mount | grep -q /srv/mediapg; then
|
||||||
|
echo "✓ mediapg unlocked and mounted at /srv/mediapg"
|
||||||
|
else
|
||||||
|
echo "✗ Failed to mount mediapg"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "ℹ mediapg pool not found (media drive may not be connected)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Optional: Mount VeraCrypt containers
|
||||||
|
if [ -f /usr/local/sbin/mount-veracrypt-vault.sh ]; then
|
||||||
|
echo "VeraCrypt container found. Mount now? (y/n)"
|
||||||
|
read -r response
|
||||||
|
if [[ "$response" == "y" ]]; then
|
||||||
|
/usr/local/sbin/mount-veracrypt-vault.sh
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=========================================="
|
||||||
|
echo " Starting Docker Services"
|
||||||
|
echo "=========================================="
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Start Docker service
|
||||||
|
if ! systemctl is-active --quiet docker; then
|
||||||
|
echo "Starting Docker..."
|
||||||
|
sudo systemctl start docker
|
||||||
|
sleep 3
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Start containers
|
||||||
|
echo "Starting Wiki.js stack..."
|
||||||
|
cd /srv/pocket-grimoire/stacks/wikijs && docker compose up -d
|
||||||
|
|
||||||
|
echo "Starting Jellyfin stack..."
|
||||||
|
cd /srv/pocket-grimoire/stacks/jellyfin && docker compose up -d
|
||||||
|
|
||||||
|
echo "Starting Stash stack..."
|
||||||
|
if [ -d /srv/pocket-grimoire/stacks/stash ]; then
|
||||||
|
cd /srv/pocket-grimoire/stacks/stash && docker compose up -d
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Optional containers
|
||||||
|
if [ -d /srv/pocket-grimoire/stacks/filebrowser ]; then
|
||||||
|
echo "Starting File Browser..."
|
||||||
|
cd /srv/pocket-grimoire/stacks/filebrowser && docker compose up -d
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=========================================="
|
||||||
|
echo " Pocket Grimoire Ready!"
|
||||||
|
echo "=========================================="
|
||||||
|
echo
|
||||||
|
echo "Services available at:"
|
||||||
|
echo " Wiki.js: http://pocket-grimoire.local:3000"
|
||||||
|
echo " Jellyfin: http://pocket-grimoire.local:8096"
|
||||||
|
echo " Stash: http://pocket-grimoire.local:9999"
|
||||||
|
echo " File Browser: http://pocket-grimoire.local:8080"
|
||||||
|
echo
|
||||||
|
echo "Total unlock time: $(($SECONDS / 60)) minutes $(($SECONDS % 60)) seconds"
|
||||||
|
echo
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo chmod +x /usr/local/sbin/unlock-pocket-grimoire.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7. Disable Docker Auto-Start (Headless Configuration)
|
||||||
|
|
||||||
|
**Prevent Docker from starting before ZFS pools are unlocked:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Disable Docker auto-start on boot
|
||||||
|
sudo systemctl disable docker
|
||||||
|
|
||||||
|
# Docker will be started manually by unlock script
|
||||||
|
```
|
||||||
|
|
||||||
|
**Or, configure Docker to wait for ZFS (if you prefer):**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo mkdir -p /etc/systemd/system/docker.service.d
|
||||||
|
sudo nano /etc/systemd/system/docker.service.d/wait-for-zfs.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[Unit]
|
||||||
|
# Don't start Docker until after manual ZFS unlock
|
||||||
|
After=zfs-mount.service
|
||||||
|
Wants=zfs-mount.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
# Restart Docker if it fails (ZFS not ready)
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=10
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
```
|
||||||
|
|
||||||
|
**Recommended: Just disable auto-start and use unlock script.**
|
||||||
|
|
||||||
|
### 8. Test Headless Unlock Procedure
|
||||||
|
|
||||||
|
**Test at home before traveling:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Reboot Pi
|
||||||
|
sudo reboot
|
||||||
|
|
||||||
|
# 2. Wait 2-3 minutes for boot (don't connect monitor/keyboard)
|
||||||
|
|
||||||
|
# 3. SSH from laptop
|
||||||
|
ssh user@pocket-grimoire.local
|
||||||
|
|
||||||
|
# 4. Run unlock script
|
||||||
|
/usr/local/sbin/unlock-pocket-grimoire.sh
|
||||||
|
|
||||||
|
# Enter passphrases when prompted:
|
||||||
|
# - VAULT passphrase
|
||||||
|
# - MEDIA-PERSONAL passphrase (if encrypted)
|
||||||
|
# - VeraCrypt password (if using)
|
||||||
|
|
||||||
|
# 5. Wait for Docker containers to start
|
||||||
|
|
||||||
|
# 6. Verify services running
|
||||||
|
docker ps
|
||||||
|
|
||||||
|
# 7. Access from browser
|
||||||
|
# http://pocket-grimoire.local:3000
|
||||||
|
# http://pocket-grimoire.local:8096
|
||||||
|
# http://pocket-grimoire.local:9999
|
||||||
|
|
||||||
|
# 8. Verify data accessible
|
||||||
|
ls /srv/vaultpg/Green/Pocket/
|
||||||
|
ls /srv/mediapg/library/
|
||||||
|
```
|
||||||
|
|
||||||
|
**If everything works, you're ready for travel!**
|
||||||
|
|
||||||
|
### 9. Quick Manual Unlock (If Script Fails)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# SSH into Pocket Grimoire
|
||||||
|
ssh user@pocket-grimoire.local
|
||||||
|
|
||||||
|
# Import pools if needed
|
||||||
|
sudo zpool import vaultpg
|
||||||
|
sudo zpool import mediapg
|
||||||
|
|
||||||
|
# Load encryption keys
|
||||||
|
sudo zfs load-key vaultpg
|
||||||
|
sudo zfs load-key mediapg # Only if MEDIA-PERSONAL (encrypted)
|
||||||
|
|
||||||
|
# Mount all datasets
|
||||||
|
sudo zfs mount -a
|
||||||
|
|
||||||
|
# Verify mounted
|
||||||
|
df -h | grep srv
|
||||||
|
|
||||||
|
# Start Docker
|
||||||
|
sudo systemctl start docker
|
||||||
|
|
||||||
|
# Start containers manually
|
||||||
|
cd /srv/pocket-grimoire/stacks/wikijs && docker compose up -d
|
||||||
|
cd /srv/pocket-grimoire/stacks/jellyfin && docker compose up -d
|
||||||
|
cd /srv/pocket-grimoire/stacks/stash && docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
**Configure ZFS to Wait for Passphrase on Boot:**
|
**Configure ZFS to Wait for Passphrase on Boot:**
|
||||||
```bash
|
```bash
|
||||||
# Edit /etc/systemd/system/zfs-load-key.service
|
# Edit /etc/systemd/system/zfs-load-key.service
|
||||||
|
|
@ -1319,24 +1716,70 @@ sudo umount /mnt/pocket-media
|
||||||
|
|
||||||
### 8. Document Passphrases
|
### 8. Document Passphrases
|
||||||
- [ ] ZFS encryption passphrases (written down, secured)
|
- [ ] ZFS encryption passphrases (written down, secured)
|
||||||
|
- VAULT (vaultpg): [write passphrase on paper]
|
||||||
|
- MEDIA-PERSONAL (mediapg): [write passphrase on paper]
|
||||||
|
- MEDIA-FAMILY: N/A (unencrypted)
|
||||||
- [ ] VeraCrypt container passwords (if using, written down, secured)
|
- [ ] VeraCrypt container passwords (if using, written down, secured)
|
||||||
- [ ] WiFi credentials for travel router (portapotty network)
|
- [ ] WiFi credentials for travel router (portapotty network)
|
||||||
- [ ] Jellyfin admin password
|
- [ ] Jellyfin admin password
|
||||||
- [ ] Wiki.js admin password
|
- [ ] Wiki.js admin password
|
||||||
|
- [ ] Stash admin password
|
||||||
- [ ] Keep all passphrases in secure location separate from device
|
- [ ] Keep all passphrases in secure location separate from device
|
||||||
|
|
||||||
### 9. Test VeraCrypt Containers (If Using)
|
### 9. Test Headless Unlock Procedure (CRITICAL)
|
||||||
```bash
|
```bash
|
||||||
# Verify container can mount
|
# At home, test the exact hotel deployment workflow
|
||||||
sudo veracrypt --text --mount \
|
|
||||||
/srv/vaultpg/veracrypt-containers/vault.vc \
|
|
||||||
/mnt/veracrypt/vault1
|
|
||||||
|
|
||||||
# Access files
|
# 1. Reboot Pi without monitor/keyboard attached
|
||||||
ls /mnt/veracrypt/vault1
|
sudo reboot
|
||||||
|
|
||||||
# Unmount
|
# 2. Wait 2-3 minutes for boot
|
||||||
sudo veracrypt --text --dismount /mnt/veracrypt/vault1
|
|
||||||
|
# 3. SSH from laptop
|
||||||
|
ssh user@pocket-grimoire.local
|
||||||
|
|
||||||
|
# 4. Run unlock script
|
||||||
|
/usr/local/sbin/unlock-pocket-grimoire.sh
|
||||||
|
|
||||||
|
# 5. Enter passphrases when prompted
|
||||||
|
# - VAULT passphrase
|
||||||
|
# - MEDIA-PERSONAL passphrase (if encrypted)
|
||||||
|
# - VeraCrypt password (if applicable)
|
||||||
|
|
||||||
|
# 6. Wait for Docker containers to start (~30 seconds)
|
||||||
|
|
||||||
|
# 7. Verify all services running
|
||||||
|
docker ps
|
||||||
|
|
||||||
|
# 8. Test access from browser
|
||||||
|
# http://pocket-grimoire.local:3000 (Wiki.js)
|
||||||
|
# http://pocket-grimoire.local:8096 (Jellyfin)
|
||||||
|
# http://pocket-grimoire.local:9999 (Stash)
|
||||||
|
|
||||||
|
# 9. Test media playback in Jellyfin
|
||||||
|
# 10. Test Stash preview playback
|
||||||
|
# 11. Test NFS mount from laptop (optional)
|
||||||
|
```
|
||||||
|
|
||||||
|
**If anything fails during this test, debug at home before traveling!**
|
||||||
|
|
||||||
|
### 10. Verify Data Synced from Netgrimoire
|
||||||
|
```bash
|
||||||
|
# Check Vault data present
|
||||||
|
ls /srv/vaultpg/Green/Pocket/stash/
|
||||||
|
ls /srv/vaultpg/Green/Pocket/media/
|
||||||
|
du -sh /srv/vaultpg/Green/Pocket/
|
||||||
|
|
||||||
|
# Check media drive populated (if applicable)
|
||||||
|
ls /srv/mediapg/library/
|
||||||
|
du -sh /srv/mediapg/
|
||||||
|
|
||||||
|
# Verify Stash database and previews
|
||||||
|
ls -lh /srv/vaultpg/Green/Pocket/stash/config/
|
||||||
|
# Should show: stash-go.sqlite
|
||||||
|
|
||||||
|
ls /srv/vaultpg/Green/Pocket/stash/generated/ | wc -l
|
||||||
|
# Should show: hundreds of preview files
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -1347,52 +1790,109 @@ sudo veracrypt --text --dismount /mnt/veracrypt/vault1
|
||||||
|
|
||||||
### Physical Setup (5 minutes)
|
### Physical Setup (5 minutes)
|
||||||
1. Unpack Pocket Grimoire enclosure
|
1. Unpack Pocket Grimoire enclosure
|
||||||
2. Connect Beryl AX to hotel WiFi (configure via phone app)
|
2. Connect Beryl AX to hotel WiFi (configure via phone app or admin panel)
|
||||||
3. Connect Pi to Beryl AX via Ethernet
|
3. Connect Pi to Beryl AX via Ethernet (CAT5 cable)
|
||||||
4. Plug Anker Prime into wall outlet
|
4. Plug Anker Prime into wall outlet
|
||||||
5. Connect all USB devices to Anker Prime
|
5. Connect all USB devices to Anker Prime:
|
||||||
|
- VAULT SSD → Anker USB-A port #2
|
||||||
|
- Media SSD (PERSONAL or FAMILY) → Pi USB 3.0 port
|
||||||
|
- Beryl AX → Anker USB-C retractable port
|
||||||
|
- Pi → Anker USB-A port #1
|
||||||
6. Power on (wait 2-3 minutes for boot)
|
6. Power on (wait 2-3 minutes for boot)
|
||||||
|
|
||||||
### ZFS Unlock (2 minutes)
|
### SSH Connection (1 minute)
|
||||||
|
```bash
|
||||||
|
# From laptop (connected to portapotty WiFi)
|
||||||
|
ssh user@pocket-grimoire.local
|
||||||
|
|
||||||
|
# If .local doesn't work, find Pi's IP:
|
||||||
|
# - Check Beryl AX admin: http://192.168.8.1
|
||||||
|
# - Look for "pocket-grimoire" in client list
|
||||||
|
# - SSH via IP: ssh user@192.168.8.50
|
||||||
|
```
|
||||||
|
|
||||||
|
### ZFS Unlock (2-3 minutes)
|
||||||
|
```bash
|
||||||
|
# Run unlock script
|
||||||
|
/usr/local/sbin/unlock-pocket-grimoire.sh
|
||||||
|
|
||||||
|
# Script will prompt for passphrases:
|
||||||
|
# Enter passphrase for 'vaultpg': [type VAULT passphrase]
|
||||||
|
# Enter passphrase for 'mediapg': [type MEDIA-PERSONAL passphrase]
|
||||||
|
# (MEDIA-FAMILY is unencrypted, no passphrase needed)
|
||||||
|
|
||||||
|
# Script automatically:
|
||||||
|
# - Unlocks ZFS pools
|
||||||
|
# - Mounts all datasets
|
||||||
|
# - Starts Docker service
|
||||||
|
# - Starts all containers (Wiki.js, Jellyfin, Stash)
|
||||||
|
# - Displays service URLs
|
||||||
|
|
||||||
|
# Total unlock time: ~2-3 minutes
|
||||||
|
```
|
||||||
|
|
||||||
|
### Verify Services (1 minute)
|
||||||
|
### Verify Services (1 minute)
|
||||||
|
```bash
|
||||||
|
# Check Docker containers running
|
||||||
|
docker ps
|
||||||
|
|
||||||
|
# Should show:
|
||||||
|
# pocketgrimoire_wikijs
|
||||||
|
# pocketgrimoire_db
|
||||||
|
# pocketgrimoire_jellyfin
|
||||||
|
# pocketgrimoire_stash
|
||||||
|
|
||||||
|
# Check ZFS pools mounted
|
||||||
|
df -h | grep srv
|
||||||
|
|
||||||
|
# Should show:
|
||||||
|
# vaultpg mounted on /srv/vaultpg
|
||||||
|
# mediapg mounted on /srv/mediapg
|
||||||
|
```
|
||||||
|
|
||||||
|
### Access Services (1 minute)
|
||||||
|
**From laptop browser (connected to portapotty WiFi):**
|
||||||
|
- Wiki.js: `http://pocket-grimoire.local:3000`
|
||||||
|
- Jellyfin: `http://pocket-grimoire.local:8096`
|
||||||
|
- Stash: `http://pocket-grimoire.local:9999`
|
||||||
|
- File Browser: `http://pocket-grimoire.local:8080` (if enabled)
|
||||||
|
|
||||||
|
**From Onn Streaming Boxes:**
|
||||||
|
- Configure Jellyfin app: Server `http://pocket-grimoire.local:8096`
|
||||||
|
- Configure StashApp: Server `http://pocket-grimoire.local:9999`
|
||||||
|
|
||||||
|
**Total setup time: ~10-12 minutes**
|
||||||
|
|
||||||
|
### If Unlock Script Fails
|
||||||
|
|
||||||
|
**Manual unlock procedure:**
|
||||||
```bash
|
```bash
|
||||||
# SSH into Pi
|
# SSH into Pi
|
||||||
ssh user@pocket-grimoire.local
|
ssh user@pocket-grimoire.local
|
||||||
|
|
||||||
# If ZFS pools didn't auto-unlock, unlock manually
|
# Import pools
|
||||||
|
sudo zpool import vaultpg
|
||||||
|
sudo zpool import mediapg
|
||||||
|
|
||||||
|
# Load encryption keys
|
||||||
sudo zfs load-key vaultpg
|
sudo zfs load-key vaultpg
|
||||||
|
sudo zfs load-key mediapg # Only if MEDIA-PERSONAL (encrypted)
|
||||||
|
|
||||||
|
# Mount datasets
|
||||||
sudo zfs mount -a
|
sudo zfs mount -a
|
||||||
|
|
||||||
sudo zfs load-key mediapg
|
# Verify
|
||||||
sudo zfs mount -a
|
df -h | grep srv
|
||||||
|
|
||||||
# Verify pools mounted
|
# Start Docker
|
||||||
zfs list
|
sudo systemctl start docker
|
||||||
|
|
||||||
|
# Start containers
|
||||||
|
cd /srv/pocket-grimoire/stacks/wikijs && docker compose up -d
|
||||||
|
cd /srv/pocket-grimoire/stacks/jellyfin && docker compose up -d
|
||||||
|
cd /srv/pocket-grimoire/stacks/stash && docker compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
### VeraCrypt Mount (Optional, 1 minute)
|
|
||||||
```bash
|
|
||||||
# If using VeraCrypt containers
|
|
||||||
# SSH into Pi (if not already)
|
|
||||||
ssh user@pocket-grimoire.local
|
|
||||||
|
|
||||||
# Mount VeraCrypt container(s)
|
|
||||||
sudo /usr/local/sbin/mount-veracrypt-vault.sh
|
|
||||||
# Enter password when prompted
|
|
||||||
|
|
||||||
# Verify mounted
|
|
||||||
df -h /mnt/veracrypt/vault1
|
|
||||||
ls /mnt/veracrypt/vault1
|
|
||||||
|
|
||||||
# Or mount manually:
|
|
||||||
sudo veracrypt --text --mount \
|
|
||||||
/srv/vaultpg/veracrypt-containers/vault.vc \
|
|
||||||
/mnt/veracrypt/vault1
|
|
||||||
|
|
||||||
# List all mounted VeraCrypt volumes
|
|
||||||
veracrypt --text --list
|
|
||||||
```
|
|
||||||
|
|
||||||
### Verify Services (2 minutes)
|
|
||||||
```bash
|
```bash
|
||||||
# Check Docker containers
|
# Check Docker containers
|
||||||
docker ps
|
docker ps
|
||||||
|
|
@ -1646,11 +2146,11 @@ htop
|
||||||
|
|
||||||
## Shutdown Procedure
|
## Shutdown Procedure
|
||||||
|
|
||||||
**Proper shutdown to protect encrypted ZFS pools:**
|
**Proper shutdown to protect encrypted ZFS pools (headless operation):**
|
||||||
|
|
||||||
### From SSH
|
### From SSH (Recommended)
|
||||||
```bash
|
```bash
|
||||||
# SSH into Pi
|
# SSH into Pi from laptop
|
||||||
ssh user@pocket-grimoire.local
|
ssh user@pocket-grimoire.local
|
||||||
|
|
||||||
# Stop Docker containers
|
# Stop Docker containers
|
||||||
|
|
@ -1660,6 +2160,9 @@ docker compose down
|
||||||
cd /srv/pocket-grimoire/stacks/jellyfin
|
cd /srv/pocket-grimoire/stacks/jellyfin
|
||||||
docker compose down
|
docker compose down
|
||||||
|
|
||||||
|
cd /srv/pocket-grimoire/stacks/stash
|
||||||
|
docker compose down
|
||||||
|
|
||||||
# Optional: Stop other containers
|
# Optional: Stop other containers
|
||||||
cd /srv/pocket-grimoire/stacks/filebrowser
|
cd /srv/pocket-grimoire/stacks/filebrowser
|
||||||
docker compose down
|
docker compose down
|
||||||
|
|
@ -1678,22 +2181,57 @@ sudo zfs unmount -a
|
||||||
sudo zpool export vaultpg
|
sudo zpool export vaultpg
|
||||||
sudo zpool export mediapg
|
sudo zpool export mediapg
|
||||||
|
|
||||||
|
# Verify pools exported
|
||||||
|
zpool list
|
||||||
|
# Should NOT show vaultpg or mediapg
|
||||||
|
|
||||||
# Shutdown Pi
|
# Shutdown Pi
|
||||||
sudo shutdown -h now
|
sudo shutdown -h now
|
||||||
|
|
||||||
# Wait 30 seconds for complete shutdown
|
# Wait 30 seconds for complete shutdown
|
||||||
# Red LED will turn off when safe to unplug
|
# Pi's green ACT LED will stop blinking
|
||||||
|
# Red power LED will turn off
|
||||||
|
# Safe to unplug power
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Total shutdown time: ~2-3 minutes**
|
||||||
|
|
||||||
### Emergency Shutdown
|
### Emergency Shutdown
|
||||||
**If SSH is unavailable:**
|
**If SSH is unavailable or Pi is unresponsive:**
|
||||||
|
|
||||||
1. Unplug Ethernet cable from Pi (stops network activity)
|
1. Stop all network activity:
|
||||||
2. Wait 10 seconds
|
- Unplug Ethernet cable from Pi
|
||||||
3. Unplug power from Anker Prime
|
- Wait 10 seconds
|
||||||
4. ZFS pools and VeraCrypt containers may need recovery on next boot (usually auto-repairs)
|
|
||||||
|
|
||||||
**Note:** ZFS is resilient, but proper shutdown is always better. VeraCrypt containers are generally safe with sudden unmount.
|
2. Power off:
|
||||||
|
- Unplug power from Anker Prime (pulls power from everything)
|
||||||
|
- Wait 10 seconds
|
||||||
|
|
||||||
|
3. Consequences:
|
||||||
|
- ZFS pools may need recovery on next boot (usually auto-repairs)
|
||||||
|
- VeraCrypt containers are generally safe with sudden unmount
|
||||||
|
- Docker containers will need restart
|
||||||
|
- No data loss expected (ZFS is resilient)
|
||||||
|
|
||||||
|
**Note:** ZFS and VeraCrypt are resilient to sudden power loss, but proper shutdown is always better for data integrity.
|
||||||
|
|
||||||
|
### Shutdown Checklist
|
||||||
|
|
||||||
|
Before leaving hotel:
|
||||||
|
- [ ] SSH into Pocket Grimoire
|
||||||
|
- [ ] Stop all Docker containers
|
||||||
|
- [ ] Unmount VeraCrypt (if using)
|
||||||
|
- [ ] Export ZFS pools (vaultpg, mediapg)
|
||||||
|
- [ ] Shutdown Pi (`sudo shutdown -h now`)
|
||||||
|
- [ ] Wait for Pi LEDs to turn off (30 seconds)
|
||||||
|
- [ ] Unplug power from Anker Prime
|
||||||
|
- [ ] Disconnect and pack all equipment
|
||||||
|
|
||||||
|
**Never skip the ZFS export step!** Exporting pools ensures:
|
||||||
|
- All data is flushed to disk
|
||||||
|
- Filesystem is marked clean
|
||||||
|
- Prevents corruption
|
||||||
|
- Allows pools to be imported cleanly on next boot
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue