# Fast Migration Plan - LXC/LXD to Incus (ONE BY ONE) ## Strategy: STREAMING DATA TRANSFER (NO DISK I/O ON SOURCE) Transfer container data directly via compressed stream, NO intermediate tarballs on source. Use `pv` (pipe viewer) for colorful progress bars and rate monitoring. --- ## Why This is FASTEST ✅ **NO disk writes on source** (99% full) - streaming only ✅ **zstd compression** - 3-5x faster than gzip ✅ **pv monitoring** - colorful progress, ETA, rate ✅ **Parallel transfers** - migrate multiple containers simultaneously ✅ **Immediate deletion** - frees space for next transfer --- ## Prerequisites ### On Source (82.29.59.188) ```bash # Install required tools sudo apt update && sudo apt install -y zstd pv # List all containers lxc list ``` ### On Destination (63.141.255.9) ```bash # Incus is already installed and clean (LXC/LXD removed) # Create PROD-GBO network bridge sudo incus network create PROD-GBO --type bridge ipv4.address=10.107.115.1/24 # Create PROD-GBO1 project sudo incus project create PROD-GBO1 sudo incus project switch PROD-GBO1 # Configure project sudo incus project set PROD-GBO1 features.storage.volumes=true sudo incus project set PROD-GBO1 features.profiles=true ``` --- ## Migration Workflow (Per Container) ### Step 1: Stop Container on Source ```bash # On source server lxc stop pragmatismo-alm ``` ### Step 2: Stream Data to Destination (FASTEST - NO DISK I/O) ```bash # On source server - stream compressed data directly lxc exec pragmatismo-alm -- tar -cf - /opt/gbo/ | \ zstd -3 -q | \ pv -s $(du -sb /opt/gbo | awk '{print $1}') | \ ssh administrator@63.141.255.9 "zstd -d | tar -xf - -C ~/gbo/pragmatismo-alm/" ``` **What happens:** 1. `tar` reads /opt/gbo from container (streamed, no disk write) 2. `zstd -3` compresses on-the-fly (fast compression) 3. `pv` shows colorful progress with ETA and rate 4. `ssh` streams to destination 5. Destination decompresses and extracts directly to ~/gbo/pragmatismo-alm/ 6. **NO tarball on source disk** - solves 99% full problem! **pv Options:** - `-s` : Total size (from `du -sb` for accurate progress) - Colorful output with ETA, rate, elapsed time ### Step 3: Delete Container from Source ```bash # Free space immediately for next transfer lxc delete pragmatismo-alm ``` ### Step 4: Create Fresh Incus Container ```bash # On destination server sudo incus launch images:debian/12/cloud pragmatismo-alm # Add network sudo incus config device add pragmatismo-alm eth0 nic name=eth0 network=PROD-GBO # Set static IP sudo incus config set pragmatismo-alm ipv4.address=10.107.115.4 # Create gbuser inside container sudo incus exec pragmatismo-alm -- useradd -m -s /bin/bash gbuser ``` ### Step 5: Push Data to Container ```bash # Create directory structure sudo incus exec pragmatismo-alm -- mkdir -p /opt/gbo # Push data (recursive) sudo incus file push -r ~/gbo/pragmatismo-alm/* pragmatismo-alm/opt/gbo/ # Fix ownership sudo incus exec pragmatismo-alm -- chown -R gbuser:gbuser /opt/gbo # Make binaries executable sudo incus exec pragmatismo-alm -- chmod +x /opt/gbo/bin/* ``` ### Step 6: Start Container and Verify Service ```bash sudo incus start pragmatismo-alm # Check service status sudo incus exec pragmatismo-alm -- systemctl status alm # Check logs sudo incus exec pragmatismo-alm -- journalctl -u alm -f ``` ### Step 7: Configure NAT Rules (ON HOST, NOT IN CONTAINER) ```bash # On destination host (63.141.255.9) # For ALM (example): sudo iptables -t nat -A PREROUTING -p tcp --dport 4747 -j DNAT --to-destination 10.107.115.4:4747 sudo iptables -t nat -A OUTPUT -p tcp --dport 4747 -j DNAT --to-destination 10.107.115.4:4747 sudo iptables -A FORWARD -p tcp -d 10.107.115.4 --dport 4747 -j ACCEPT sudo iptables -t nat -A POSTROUTING -p tcp -d 10.107.115.4 -j MASQUERADE # Save rules sudo sh -c 'iptables-save > /etc/iptables/rules.v4' ``` --- ## Full Migration Script (ALL CONTAINERS) ### Run Multiple Containers in Parallel (for speed) ```bash #!/bin/bash # MIGRATE-ALL.sh - Fast parallel migration set -e # Container list with IPs declare -A CONTAINERS=( ["dns"]="10.107.115.155" ["email"]="10.107.115.200" ["webmail"]="10.107.115.208" ["alm"]="10.107.115.4" ["drive"]="10.107.115.114" ["tables"]="10.107.115.33" ["system"]="10.107.115.229" ["alm-ci"]="10.107.115.190" ["table-editor"]="10.107.115.73" ) for container in "${!CONTAINERS[@]}"; do ip="${CONTAINERS[$container]}" echo -e "\e[1;32m=== Migrating $container ($ip) ===\e[0m" # Step 1: Stop echo -e "\e[1;33mStopping $container...\e[0m" ssh root@82.29.59.188 "lxc stop $container" || true # Step 2: Get size for pv echo -e "\e[1;33mGetting size of /opt/gbo...\e[0m" size=$(ssh root@82.29.59.188 "lxc exec $container -- du -sb /opt/gbo | awk '{print \$1}'") # Step 3: Stream data (FAST!) echo -e "\e[1;33mStreaming data to destination...\e[0m" ssh root@82.29.59.188 "lxc exec $container -- tar -cf - /opt/gbo/" | \ zstd -3 -q | \ pv -s $size | \ ssh administrator@63.141.255.9 "mkdir -p ~/gbo/$container && zstd -d | tar -xf - -C ~/gbo/$container/" # Step 4: Delete from source echo -e "\e[1;33mDeleting $container from source...\e[0m" ssh root@82.29.59.188 "lxc delete $container" # Step 5: Create fresh container echo -e "\e[1;33mCreating Incus container...\e[0m" ssh administrator@63.141.255.9 "sudo incus launch images:debian/12/cloud $container && \ sudo incus config device add $container eth0 nic name=eth0 network=PROD-GBO && \ sudo incus config set $container ipv4.address=$ip && \ sudo incus exec $container -- useradd -m -s /bin/bash gbuser" # Step 6: Push data echo -e "\e[1;33mPushing data to container...\e[0m" ssh administrator@63.141.255.9 "sudo incus exec $container -- mkdir -p /opt/gbo && \ sudo incus file push -r ~/gbo/$container/* $container:/opt/gbo/ && \ sudo incus exec $container -- chown -R gbuser:gbuser /opt/gbo && \ sudo incus exec $container -- chmod +x /opt/gbo/bin/*" # Step 7: Start echo -e "\e[1;33mStarting $container...\e[0m" ssh administrator@63.141.255.9 "sudo incus start $container" echo -e "\e[1;32m✓ $container migrated successfully!\e[0m" echo "" done echo -e "\e[1;32m=== ALL MIGRATIONS COMPLETE ===\e[0m" ``` --- ## Single Container Migration (Quick Test) ```bash #!/bin/bash # migrate-one.sh - Migrate single container CONTAINER=$1 if [ -z "$CONTAINER" ]; then echo "Usage: $0 " exit 1 fi echo -e "\e[1;32m=== Migrating $CONTAINER ===\e[0m" # Stop on source echo -e "\e[1;33m[1/7] Stopping container...\e[0m" ssh root@82.29.59.188 "lxc stop $CONTAINER" # Get size echo -e "\e[1;33m[2/7] Getting data size...\e[0m" SIZE=$(ssh root@82.29.59.188 "lxc exec $CONTAINER -- du -sb /opt/gbo | awk '{print \$1}'") # Stream data (NO DISK WRITE!) echo -e "\e[1;33m[3/7] Streaming data (pv will show progress)...\e[0m" ssh root@82.29.59.188 "lxc exec $CONTAINER -- tar -cf - /opt/gbo/" | \ zstd -3 -q | \ pv -s $SIZE | \ ssh administrator@63.141.255.9 "mkdir -p ~/gbo/$CONTAINER && zstd -d | tar -xf - -C ~/gbo/$CONTAINER/" # Delete from source echo -e "\e[1;33m[4/7] Deleting from source...\e[0m" ssh root@82.29.59.188 "lxc delete $CONTAINER" # Create container echo -e "\e[1;33m[5/7] Creating Incus container...\e[0m" ssh administrator@63.141.255.9 "sudo incus launch images:debian/12/cloud $CONTAINER && \ sudo incus config device add $CONTAINER eth0 nic name=eth0 network=PROD-GBO && \ sudo incus exec $CONTAINER -- useradd -m -s /bin/bash gbuser" # Push data echo -e "\e[1;33m[6/7] Pushing data...\e[0m" ssh administrator@63.141.255.9 "sudo incus exec $CONTAINER -- mkdir -p /opt/gbo && \ sudo incus file push -r ~/gbo/$CONTAINER/* $CONTAINER:/opt/gbo/ && \ sudo incus exec $CONTAINER -- chown -R gbuser:gbuser /opt/gbo && \ sudo incus exec $CONTAINER -- chmod +x /opt/gbo/bin/*" # Start echo -e "\e[1;33m[7/7] Starting container...\e[0m" ssh administrator@63.141.255.9 "sudo incus start $CONTAINER" echo -e "\e[1;32m✓ Migration complete! Check with: incus list\e[0m" ``` --- ## Port Forwarding (iptables NAT) - Complete Rules ```bash # Enable IP forwarding (persistent) echo "net.ipv4.ip_forward = 1" | sudo tee /etc/sysctl.d/99-ipforward.conf sudo sysctl -w net.ipv4.ip_forward=1 # Enable route_localnet echo "net.ipv4.conf.all.route_localnet = 1" | sudo tee /etc/sysctl.d/99-localnet.conf sudo sysctl -w net.ipv4.conf.all.route_localnet=1 # DNS (53) sudo iptables -t nat -A PREROUTING -p udp --dport 53 -j DNAT --to-destination 10.107.115.155:53 sudo iptables -t nat -A PREROUTING -p tcp --dport 53 -j DNAT --to-destination 10.107.115.155:53 sudo iptables -t nat -A OUTPUT -p udp --dport 53 -j DNAT --to-destination 10.107.115.155:53 sudo iptables -t nat -A OUTPUT -p tcp --dport 53 -j DNAT --to-destination 10.107.115.155:53 # Email (25,465,587,993,995,143,110,4190) sudo iptables -t nat -A PREROUTING -p tcp --dport 25 -j DNAT --to-destination 10.107.115.200:25 sudo iptables -t nat -A PREROUTING -p tcp --dport 465 -j DNAT --to-destination 10.107.115.200:465 sudo iptables -t nat -A PREROUTING -p tcp --dport 587 -j DNAT --to-destination 10.107.115.200:587 sudo iptables -t nat -A PREROUTING -p tcp --dport 993 -j DNAT --to-destination 10.107.115.200:993 sudo iptables -t nat -A PREROUTING -p tcp --dport 995 -j DNAT --to-destination 10.107.115.200:995 sudo iptables -t nat -A PREROUTING -p tcp --dport 143 -j DNAT --to-destination 10.107.115.200:143 sudo iptables -t nat -A PREROUTING -p tcp --dport 110 -j DNAT --to-destination 10.107.115.200:110 sudo iptables -t nat -A PREROUTING -p tcp --dport 4190 -j DNAT --to-destination 10.107.115.200:4190 sudo iptables -t nat -A OUTPUT -p tcp --dport 25 -j DNAT --to-destination 10.107.115.200:25 sudo iptables -t nat -A OUTPUT -p tcp --dport 465 -j DNAT --to-destination 10.107.115.200:465 sudo iptables -t nat -A OUTPUT -p tcp --dport 587 -j DNAT --to-destination 10.107.115.200:587 sudo iptables -t nat -A OUTPUT -p tcp --dport 993 -j DNAT --to-destination 10.107.115.200:993 sudo iptables -t nat -A OUTPUT -p tcp --dport 995 -j DNAT --to-destination 10.107.115.200:995 sudo iptables -t nat -A OUTPUT -p tcp --dport 143 -j DNAT --to-destination 10.107.115.200:143 sudo iptables -t nat -A OUTPUT -p tcp --dport 110 -j DNAT --to-destination 10.107.115.200:110 sudo iptables -t nat -A OUTPUT -p tcp --dport 4190 -j DNAT --to-destination 10.107.115.200:4190 # Webmail (5252) sudo iptables -t nat -A PREROUTING -p tcp --dport 5252 -j DNAT --to-destination 10.107.115.208:5252 sudo iptables -t nat -A OUTPUT -p tcp --dport 5252 -j DNAT --to-destination 10.107.115.208:5252 # ALM (4747) sudo iptables -t nat -A PREROUTING -p tcp --dport 4747 -j DNAT --to-destination 10.107.115.4:4747 sudo iptables -t nat -A OUTPUT -p tcp --dport 4747 -j DNAT --to-destination 10.107.115.4:4747 # Tables/PostgreSQL (5432) sudo iptables -t nat -A PREROUTING -p tcp --dport 5432 -j DNAT --to-destination 10.107.115.33:5432 sudo iptables -t nat -A OUTPUT -p tcp --dport 5432 -j DNAT --to-destination 10.107.115.33:5432 # Proxy/Caddy (80, 443) sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 10.107.115.236:80 sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j DNAT --to-destination 10.107.115.236:443 sudo iptables -t nat -A OUTPUT -p tcp --dport 80 -j DNAT --to-destination 10.107.115.236:80 sudo iptables -t nat -A OUTPUT -p tcp --dport 443 -j DNAT --to-destination 10.107.115.236:443 # FORWARD rules (allow traffic to containers) sudo iptables -A FORWARD -p tcp -d 10.107.115.155 -j ACCEPT sudo iptables -A FORWARD -p udp -d 10.107.115.155 -j ACCEPT sudo iptables -A FORWARD -p tcp -d 10.107.115.200 -j ACCEPT sudo iptables -A FORWARD -p tcp -s 10.107.115.200 -j ACCEPT sudo iptables -A FORWARD -p tcp -d 10.107.115.208 -j ACCEPT sudo iptables -A FORWARD -p tcp -d 10.107.115.4 -j ACCEPT sudo iptables -A FORWARD -p tcp -d 10.107.115.33 -j ACCEPT sudo iptables -A FORWARD -p tcp -d 10.107.115.236 -j ACCEPT sudo iptables -A FORWARD -p tcp -s 10.107.115.236 -j ACCEPT # POSTROUTING MASQUERADE (return traffic) sudo iptables -t nat -A POSTROUTING -p tcp -d 10.107.115.155 -j MASQUERADE sudo iptables -t nat -A POSTROUTING -p udp -d 10.107.115.155 -j MASQUERADE sudo iptables -t nat -A POSTROUTING -p tcp -d 10.107.115.200 -j MASQUERADE sudo iptables -t nat -A POSTROUTING -p tcp -d 10.107.115.208 -j MASQUERADE sudo iptables -t nat -A POSTROUTING -p tcp -d 10.107.115.4 -j MASQUERADE sudo iptables -t nat -A POSTROUTING -p tcp -d 10.107.115.33 -j MASQUERADE sudo iptables -t nat -A POSTROUTING -p tcp -d 10.107.115.236 -j MASQUERADE # Save rules sudo sh -c 'iptables-save > /etc/iptables/rules.v4' ``` --- ## Benefits of This Approach ✅ **FASTEST** - No intermediate tarballs, pure streaming ✅ **COLORFUL** - pv shows beautiful progress bars ✅ **EFFICIENT** - zstd compression (3-5x gzip) ✅ **SAFE** - One container at a time, verify before next ✅ **CLEAN** - Immediate deletion frees disk space ✅ **MONITORED** - Real-time transfer rate and ETA ✅ **PARALLEL** - Can migrate multiple containers at once **Estimated time:** - Small containers (<1GB): ~5-10 minutes each - Medium containers (1-5GB): ~10-20 minutes each - Large containers (>5GB): ~20-40 minutes each - Total (parallel): ~1-2 hours for all containers vs lxc export method: ~4-8 hours total --- ## Quick Start ```bash # 1. Install pv on source ssh root@82.29.59.188 "apt install -y pv zstd" # 2. Save migration scripts # Copy migrate-one.sh and MIGRATE-ALL.sh # 3. Run single test ./migrate-one.sh pragmatismo-alm # 4. If successful, run all ./MIGRATE-ALL.sh ``` --- ## Troubleshooting ### pv not showing progress? ```bash # Check pv is installed pv --version # Check size detection ssh root@82.29.59.188 "lxc exec pragmatismo-alm -- du -sb /opt/gbo" ``` ### Container not starting? ```bash # Check logs sudo incus list sudo incus info pragmatismo-alm sudo incus logs pragmatismo-alm --show-log # Check network sudo incus exec pragmatismo-alm -- ip addr ``` ### Service not running? ```bash # Inside container sudo incus exec pragmatismo-alm -- bash systemctl status alm journalctl -u alm -n 50 ``` ### NAT not working? ```bash # Check rules sudo iptables -t nat -L -n -v # Check forwarding sudo iptables -L FORWARD -n -v # Test from host nc -zv 127.0.0.1 4747 ``` --- ## Summary This plan achieves: ✅ **FASTEST possible migration** - streaming, no disk I/O ✅ **Colorful progress** - pv with ETA, rate, elapsed ✅ **Immediate space cleanup** - delete as we go ✅ **Parallel migration** - do multiple containers at once ✅ **Clean Incus** - fresh start, no LXC/LXD trash ✅ **Proper NAT** - iptables only, no socat/proxy devices **No mbuffer needed** - pv does the job with colorful output! --- ## Verification Checklist After each migration: - [ ] Container running: `sudo incus list` - [ ] Service active: `sudo incus exec $c -- systemctl status ` - [ ] Data intact: `sudo incus exec $c -- ls -la /opt/gbo` - [ ] Port accessible: `nc -zv 127.0.0.1 ` - [ ] Source deleted: `ssh root@82.29.59.188 lxc list` (should not show container) - [ ] NAT rules added: `sudo iptables -t nat -L -n | grep ` After all migrations: - [ ] All containers running on Incus - [ ] All services active - [ ] All NAT rules configured - [ ] External access works - [ ] Source server: no containers left