From local to cloud: the survival guide for migrating Distrobox and Podman containers
Back to blog

From local to cloud: the survival guide for migrating Distrobox and Podman containers

6/7/2026 · 8 min · Infrastructure

I recently made a strategic decision for my workflow: moving my local development environments to a robust cloud VM (OVH). The goal? To transform my laptop into a thin client and offload heavy processing to a dedicated server.

During this transition, I faced significant networking hurdles, including international latency and inconsistent routing (especially operating from Northern Brazil). This is a technical teardown of how I migrated my Distrobox environments and Podman containers without losing a single configuration bit.

1) The starting point: creating a backup snapshot#

Distrobox is remarkable for its fluid integration with the host's /home directory, but under the hood, it is managed by Podman. To migrate the entire environment (binaries in /usr/bin, system configurations in /etc, and libraries installed via apt), the first step is to freeze the "active" container into a static image.

In my scenario, I had a development container named kali-dev. The command to generate the snapshot was:

# Committing the running container to a local static image
podman commit kali-dev kali-cloud-image

1.1) Podman version checking and compatibility#

Before proceeding, it is essential to verify the Podman version on both the local and remote target hosts to avoid runtime compatibility issues (e.g., mismatch between runc and crun, or OCI specification differences):

# Check local version
podman --version

# Check target remote version
ssh user@remote-ip "podman --version"

# Inspect detailed container runtime settings
podman info | grep -i "version\|runtime"

If there is a major version mismatch (e.g., Podman v3 vs v4), certain Distrobox flags or rootless container mounting options might fail to initialize on the destination host.

1.2) Validating local image integrity#

Before serializing the image, validate that it was created successfully in the local registry:

# Check local image registry
podman images | grep kali-cloud-image

# Check the actual size of the image in the local storage
podman image inspect kali-cloud-image | jq '.[0].Size'

Once validated, serialize the image into a transportable .tar archive:

# Exporting the image into an indexed .tar archive
podman save localhost/kali-cloud-image -o backup_ambiente.tar

After exporting, verify the integrity of the resulting tarball archive to ensure no write errors occurred:

# Check physical file size
du -sh backup_ambiente.tar

# Test structure and logical integrity of the tarball
tar -tvf backup_ambiente.tar | head -10

1.3) Structured backup of personal files (dotfiles and projects)#

Keep in mind that Distrobox mounts your host /home directory transparently. This means your personal files, SSH keys, dotfiles, and git repositories are not stored inside the exported container image. They must be backed up and migrated separately.

We can create a compressed archive, explicitly excluding local cache and Podman storage directories that would cause unnecessary storage overhead and duplicate data:

# Selective backup excluding heavy caches and temporary directories
tar czf home-backup.tar.gz \
  --exclude='.cache' \
  --exclude='node_modules' \
  --exclude='.local/share/containers' \
  ~/dotfiles ~/projects ~/Documents

Alternatively, you can prepare a direct rsync synchronization during the transfer phase.

2) The latency challenge: fighting international network physics#

Attempting to upload a multi-gigabyte file to a server in Canada (OVH) from a home connection in Brazil is a study in patience and networking theory.

2.1) Measuring network latency and bandwidth#

Before starting large file transfers, run a complete network diagnostic to assess maximum throughput and round-trip latency (RTT):

# Basic ping to verify packet loss and average latency (RTT)
ping -c 10 remote-ip

# Map network hops to locate routing bottlenecks
traceroute remote-ip

# Perform dynamic, real-time network analysis
mtr --report --report-cycles=10 remote-ip

If the remote host is running the iperf3 daemon, perform a real TCP bandwidth test to determine the actual transfer capacity supported by the physical path:

# Run client-side bandwidth test for 30 seconds
iperf3 -c remote-ip -t 30

2.2) Transfer methods and performance#

Attempt 1: The "naive" rsync#

I started with the classic rsync to ensure integrity and utilize basic compression:

rsync -vhP backup_ambiente.tar user@remote-ip:~/

Diagnosis: The rsync delta-transfer algorithm combined with protocol overhead resulted in a pathetic throughput of 600 KiB/s. Estimated time: +7 hours. This was operationally unacceptable for a professional workflow.

Attempt 2: SSH pipe with gzip and pipe viewer (pv)#

To maximize throughput, I shifted to real-time compression and optimized SSH ciphers:

pv backup_ambiente.tar | gzip -1 -c | ssh -c [email protected] user@remote-ip "gunzip -c > ~/backup_ambiente.tar"

Technical Insight: The pv utility provided real-time telemetry. It became clear that the bottleneck wasn't the CPU (compression speed) but the international peering of the ISP. The direct route from Brazil to Canada was suffering from saturated ISP buffers and packet loss at Tier 2 routing points. We can also test the physical transfer speed by routing the traffic to /dev/null on the destination to isolate disk I/O bottlenecks:

pv backup_ambiente.tar | ssh user@remote-ip "cat > /dev/null"

3) Transfer security and resource validation#

Working with cloud servers requires using secure transport protocols and assessing resource capacity.

3.1) Disk space verification#

Before sending files that are tens of gigabytes in size, verify that the remote host has enough available storage on the target partition where Podman stores images. Running out of space during a write operations results in silent failures or filesystem corruption:

# Verify available disk space at the destination
ssh user@remote-ip "df -h ~"

# Compare the local file size with the remote available space
echo "Local File Size: $(du -sh backup_ambiente.tar | awk '{print $1}')"
echo "Remote Available Space: $(ssh user@remote-ip 'df -h ~' | tail -1 | awk '{print $4}')"

3.2) SSH keys and known_hosts#

Verify that your local SSH keyring is loaded and that the target host's public key is in your known_hosts file to prevent unexpected prompts or connection timeouts:

# List active keys in your SSH agent
ssh-add -l

# Check if the remote host public key is registered in known_hosts
ssh-keygen -F remote-ip

3.3) Secure sync and cryptographic verification (checksum)#

Always use strong cryptographic key configurations. After transfer, it is critical to run a checksum validation using SHA-256 to ensure no bits were corrupted during transmission:

# Generate SHA-256 hash locally
sha256sum backup_ambiente.tar

# Generate SHA-256 hash on the remote host
ssh user@remote-ip "sha256sum ~/backup_ambiente.tar"

The resulting checksum hashes on both sides must match exactly.

4) The master strategy: the "jump server" (relay stratagem)#

As an infrastructure professional, I realized that fighting the direct physical route was a losing battle. The solution was to apply a Relay using an intermediate VM in the Oracle Cloud located in São Paulo (Vinhedo).

The Human Routing Table Logic:

  1. Local → Oracle (São Paulo): Connection via IX.BR (PTT). Domestic routing, extremely low latency, and 100% utilization of my upload bandwidth.
  2. Oracle → OVH (Canada): Datacenter-to-Datacenter communication via Tier 1 backbones. Oracle and OVH share direct peering at major US exchange points, allowing transfer speeds in the hundreds of Megabits per second.

Execution: I uploaded the file to the Oracle node in 10 minutes. The subsequent transfer from Oracle to OVH took less than 2 minutes.

5) Restoring the environment at the destination (cloud)#

Once the .tar archive reached the final VM, the "rehydration" process was performed after validating target file permissions and network topology.

5.1) File permissions verification#

Before running the import, check that the file has the correct permissions so the Podman daemon can read it (especially when operating in rootless mode):

# Check file owner and permissions on the remote host
ssh user@remote-ip "ls -la ~/backup_ambiente.tar"

# Inspect detailed ownership details
ssh user@remote-ip "stat ~/backup_ambiente.tar"

If necessary, adjust the owner to the correct user running rootless Podman.

5.2) Image rehydration and container creation#

With the file validated, load the image logic into the remote Podman registry:

# Importing the image into the remote Podman registry
podman load -i backup_ambiente.tar

Once loaded, verify that the image is registered properly and that the original environment variables are preserved:

# Verify the imported image at the destination
podman images | grep kali-cloud-image

# Inspect environment variables and image metadata
podman image inspect localhost/kali-cloud-image | jq '.[0].Config.Env'

Recreate the container inside Distrobox:

# Re-creating the entry in Distrobox
distrobox create --name kali-prod --image localhost/kali-cloud-image

5.3) Permissions and target network verification#

Rootless Podman containers depend on correctly configured user namespaces and firewall policies. Validate the target host networking settings before exposing any complex services:

# Inspect available network interfaces on the remote host
ssh user@remote-ip "ip addr show"

# View target routing tables
ssh user@remote-ip "ip route show"

# List active firewall rules (iptables or firewalld)
ssh user@remote-ip "sudo iptables -L -n -v"

# Check active listening daemon ports to avoid exposure conflicts
ssh user@remote-ip "ss -lntp"

6) Post-migration and container validation#

Once the container is created and started, it is mandatory to run a detailed validation checklist inside the box to verify functionality.

6.1) Post-migration verification script#

Access the container via Distrobox and confirm identity and configuration details:

# Verify container starts and displays the correct user namespace
distrobox enter kali-prod -- whoami

# Check if essential binaries and dependencies are present
distrobox enter kali-prod -- bash -c "which python3 && which git && which curl && which nmap"

# Verify that shell variables and aliases from .bashrc are preserved
distrobox enter kali-prod -- cat ~/.bashrc | head -10

# Validate presence and ownership of mapped dotfiles in home directory
distrobox enter kali-prod -- ls -la ~/

6.2) Network connectivity and package auditing#

Verify external communication and count system packages:

# Test external connectivity from within the container
distrobox enter kali-prod -- curl -I https://google.com

# Count installed system packages to ensure no package loss occurred
distrobox enter kali-prod -- dpkg -l | wc -l

Checklist: migrating Distrobox from local to cloud#

1. Pre-migration#

2. Export and archiving#

3. Latency and connectivity#

4. Secure transfer#

5. Import and rehydration#

6. Post-migration validation#

Risk matrix and troubleshooting#

Risk ItemSeverityTechnical DescriptionMitigation / Corrective Action
Podman Version MismatchMediumRuntime differences (e.g., crun vs runc) or OCI format changes can prevent container startup.Run podman info on both sides and upgrade Podman on the host running the older version.
File Corruption in TransitHighPacket loss and routing instabilities over international links can corrupt the image tarball.Run SHA-256 checksum checks (sha256sum) on both ends and verify they match before loading.
Out of Space / Disk ExhaustionHighImage archive exceeds storage limits in the target /home or /var/lib/containers partition.Check space with df -h before sending, and clean unused images with podman system prune -a.
Firewall / Whitelist BypassMediumRigid host-level firewall rules block out-of-container rootless Podman network virtualization.Validate masquerade/NAT routing, and verify port mapping configurations via ss -lntp.
Incorrect File PermissionsMediumTarget user cannot read the transferred tarball due to rootless isolation limits.Adjust ownership with chown and apply readable permissions using chmod 644.
Personal File LossHighUser assumes files inside host home are packed in the container image, losing local datasets.Run a separate backup for dotfiles and user workspaces using tar or rsync configurations.
Unstable Link PerformanceLowHigh latency or low upload speeds prevent direct upload of container images.Use the Jump Server / Relay routing technique via a geographically closer public cloud node.

SRE lessons for your playbook#

My workspace is now 100% cloud-based, accessible via SSH from anywhere, with heavy lifting occurring far away from my local hardware.

Was this article helpful?

Leave a quick reaction to help prioritize future technical guides:

CC BY-NC

This post is licensed under CC BY-NC.

Comments

Join the discussion below.

0 comments