claude-home/vm-management/wave2-migration-results.md
Cal Corum 4b7eca8a46
All checks were successful
Reindex Knowledge Base / reindex (push) Successful in 3s
docs: add YAML frontmatter to all 151 markdown files
Adds title, description, type, domain, and tags frontmatter to every
doc for improved KB semantic search. The description field is prepended
to every search chunk, and domain/type/tags enable filtered queries.

Type values: context, guide, runbook, reference, troubleshooting
Domain values match directory structure (networking, docker, etc.)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 09:00:44 -05:00

287 lines
8.0 KiB
Markdown

---
title: "Wave 2 Migration Results"
description: "Results from migrating docker-vpn (VM 121) to arr-stack LXC 221. Documents VPN elimination rationale, Overseerr-to-Jellyseerr switch, and arr stack (Sonarr/Radarr/Readarr/SABnzbd) deployment."
type: reference
domain: vm-management
tags: [proxmox, lxc, migration, docker, arr-stack, sonarr, radarr, jellyseerr, usenet]
---
# Wave 2 Migration Results - docker-vpn (VM 121 → LXC 221 arr-stack)
**Date**: 2025-12-05
**Status**: **SUCCESSFUL**
**Migration Time**: ~2 hours
---
## Summary
Successfully migrated and restructured docker-vpn VM (121) to arr-stack LXC (221). The migration involved a significant architecture simplification - eliminating the Mullvad VPN entirely since only Usenet is used (SSL to Usenet provider is sufficient, no torrents). Additionally replaced Overseerr with Jellyseerr for native Jellyfin support.
---
## Migration Details
### Source (VM 121 - docker-vpn)
- **OS**: Ubuntu (in VM)
- **Services**: Sonarr, Radarr, Readarr, Overseerr, SABnzbd, Mullvad VPN
- **Architecture**: All traffic routed through Mullvad VPN container
- **Complexity**: High (VPN routing, multiple network namespaces)
### Destination (LXC 221 - arr-stack)
- **OS**: Ubuntu 20.04 LTS (privileged LXC)
- **Resources**: 2 cores, 4GB RAM, 32GB disk
- **IP**: 10.10.0.221
- **Services**: Sonarr, Radarr, Readarr, Jellyseerr, SABnzbd
- **Architecture**: Direct network access (no VPN)
- **Complexity**: Low (standard Docker containers)
---
## Architecture Changes
### Before (docker-vpn)
```
Internet
Mullvad VPN Container
↓ (all traffic tunneled)
├─ Sonarr
├─ Radarr
├─ Readarr
├─ Overseerr
└─ SABnzbd
```
### After (arr-stack)
```
Internet
↓ (direct, SSL encrypted to Usenet)
├─ Sonarr
├─ Radarr
├─ Readarr
├─ Jellyseerr (replaced Overseerr)
└─ SABnzbd
```
### Key Decision: VPN Elimination
**Rationale**:
- Only using Usenet (not torrents)
- Usenet providers support SSL encryption
- SSL to Usenet provider provides sufficient privacy
- VPN added complexity without meaningful benefit
- Simplified troubleshooting and maintenance
---
## Technical Implementation
### LXC Configuration
```
# /etc/pve/lxc/221.conf
arch: amd64
cores: 2
features: nesting=1,keyctl=1
hostname: arr-stack
memory: 4096
net0: name=eth0,bridge=vmbr0,gw=10.10.0.1,ip=10.10.0.221/24,type=veth
ostype: ubuntu
rootfs: local-lvm:vm-221-disk-0,size=32G
swap: 512
lxc.apparmor.profile: unconfined
```
### Docker Compose
```yaml
services:
sonarr:
image: linuxserver/sonarr:latest
container_name: sonarr
ports: ["8989:8989"]
volumes:
- ./config/sonarr:/config
- /mnt/media:/media
security_opt: [apparmor=unconfined]
restart: unless-stopped
radarr:
image: linuxserver/radarr:latest
container_name: radarr
ports: ["7878:7878"]
volumes:
- ./config/radarr:/config
- /mnt/media:/media
security_opt: [apparmor=unconfined]
restart: unless-stopped
readarr:
image: ghcr.io/hotio/readarr:latest
container_name: readarr
ports: ["8787:8787"]
volumes:
- ./config/readarr:/config
- /mnt/media:/media
security_opt: [apparmor=unconfined]
restart: unless-stopped
jellyseerr:
image: fallenbagel/jellyseerr:latest
container_name: jellyseerr
ports: ["5055:5055"]
volumes:
- ./config/jellyseerr:/app/config
security_opt: [apparmor=unconfined]
restart: unless-stopped
sabnzbd:
image: linuxserver/sabnzbd:latest
container_name: sabnzbd
ports: ["8080:8080"]
volumes:
- ./config/sabnzbd:/config
- ./downloads:/downloads
- /mnt/media:/media
security_opt: [apparmor=unconfined]
restart: unless-stopped
```
### CIFS Mount
```fstab
//10.10.0.35/media /mnt/media cifs vers=3.0,uid=0,credentials=/root/.smbcredentials 0 0
```
---
## Issues Encountered & Solutions
### Issue 1: linuxserver.io Registry (lscr.io) Pull Failures
**Problem**: `no matching manifest for linux/amd64` errors from lscr.io registry
**Solution**: Switched to Docker Hub images directly (`linuxserver/sonarr` instead of `lscr.io/linuxserver/sonarr`)
### Issue 2: Readarr Image Not Available
**Problem**: linuxserver/readarr:develop tag not available for amd64
**Solution**: Switched to hotio image (`ghcr.io/hotio/readarr:latest`)
### Issue 3: Jellyseerr Tag Validation Error
**Problem**: Radarr rejecting requests with "Label: Allowed characters a-z, 0-9 and -"
**Cause**: Jellyseerr sending tags with invalid characters to Radarr
**Solution**: Disabled tags in Jellyseerr Radarr integration settings
---
## Data Migration
### Configs Migrated
- **Sonarr**: ~1.4GB (database, MediaCover cache, backups)
- **Radarr**: ~1.6GB (database, MediaCover cache, backups)
- **Readarr**: ~88MB (database, backups)
- **Overseerr**: ~7.7MB (database, settings) - Not used, replaced with Jellyseerr
### Fresh Configuration Required
- **SABnzbd**: Fresh install (user configured Usenet provider)
- **Jellyseerr**: Fresh install (connected to Jellyfin)
---
## Validation Results
| Service | Port | Status | Test |
|---------|------|--------|------|
| Sonarr | 8989 | HTTP 200 | Database loaded, shows configured |
| Radarr | 7878 | HTTP 200 | Database loaded, movie requests working |
| Readarr | 8787 | HTTP 200 | Database loaded, shows configured |
| Jellyseerr | 5055 | HTTP 307 | Connected to Jellyfin, requests working |
| SABnzbd | 8080 | HTTP 303 | Configured with Usenet provider |
| CIFS Mount | - | Working | Media accessible in containers |
---
## Resource Comparison
### Before (VM 121)
- **Memory**: Full VM overhead (~1-2GB for OS)
- **Disk**: Larger allocation for VM image
- **Complexity**: VPN routing, multiple network namespaces
- **Maintenance**: VPN updates, connection monitoring
### After (LXC 221)
- **Memory**: ~100MB LXC overhead
- **Disk**: 32GB (minimal)
- **Complexity**: Standard Docker containers
- **Maintenance**: Standard container updates only
### Efficiency Gains
- **~1.5GB RAM saved** (VM overhead eliminated)
- **Simplified networking** (no VPN routing)
- **Reduced attack surface** (fewer services)
- **Faster boot time** (LXC vs VM)
---
## NPM/Reverse Proxy Updates
Updated Nginx Proxy Manager entries to point to new IP:
- sonarr.manticorum.com → 10.10.0.221:8989
- radarr.manticorum.com → 10.10.0.221:7878
- readarr.manticorum.com → 10.10.0.221:8787
- jellyseerr.manticorum.com → 10.10.0.221:5055 (new, replaces overseerr)
- sabnzbd.manticorum.com → 10.10.0.221:8080
---
## Rollback Capability
- **VM 121 preserved**: Can be restarted if issues arise
- **Rollback time**: <5 minutes
- **Recommendation**: Keep VM 121 stopped for 48 hours, then decommission
---
## Key Learnings
### 1. VPN Complexity Often Unnecessary
For Usenet-only setups, VPN adds complexity without meaningful benefit. SSL to the Usenet provider is sufficient.
### 2. Image Registry Issues
lscr.io can have availability issues. Docker Hub images work as fallback.
### 3. Application Substitution
Jellyseerr is a drop-in replacement for Overseerr with native Jellyfin support - worth the switch if using Jellyfin.
### 4. Tag/Label Validation
When connecting Jellyseerr to arr apps, be careful with tag configurations - invalid characters cause silent failures.
---
## Next Steps
### Immediate
- [x] Configure SABnzbd with Usenet provider
- [x] Connect arr apps to new SABnzbd
- [x] Update NPM reverse proxy entries
- [x] Test movie/show requests through Jellyseerr
### After 48 Hours
- [ ] Decommission VM 121 (docker-vpn)
- [ ] Clean up local migration temp files (`/tmp/arr-config-migration/`)
---
## Files Created/Modified
### On LXC 221
- `/opt/arr-stack/docker-compose.yml`
- `/opt/arr-stack/config/` (all service configs)
- `/root/.smbcredentials`
- `/etc/fstab` (CIFS mount)
### Documentation Updated
- `vm-management/lxc-migration-plan.md` - Wave 2 status
- `networking/server-inventory.md` - Added arr-stack entry
- `vm-management/wave2-migration-results.md` - This file
---
**Status**: **Wave 2 Complete - Ready for Wave 3**
**Contact**: Cal Corum (cal.corum@gmail.com)