- Add LXC migration plan and quick-start guide - Add wave 1 and wave 2 migration results - Add lxc-docker-create.sh for container creation - Add fix-docker-apparmor.sh for AppArmor issues - Add comprehensive LXC migration guide 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
279 lines
7.6 KiB
Markdown
279 lines
7.6 KiB
Markdown
# 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)
|