Rootless Podman volumes: how to keep data safe across upgrades without root

Rootless Podman Volumes: Keeping Your Data Safe Across Upgrades

Rootless Podman lets you run containers without ever touching sudo.
That’s great, but it also means every volume lives in your home directory.
When you bump Podman or your distro, the storage layout can change and all your data can get wiped.
Below is a practical, coffee‑talk style walk‑through that shows how to sidestep this trap.


Why Rootless Volumes Are Different

When you run

podman run --volume /data:/data …

Podman creates a directory under

~/.local/share/containers/storage/volumes/<volume-name>/_data

It’s owned by you, so no root is needed.
The problem? That whole tree lives in your home.
A major upgrade can rewrite the storage format and delete the old tree or move it elsewhere.


The Upgrade Problem in Practice

Say you have a database container:

podman run -d --name mydb \
  -v db-data:/var/lib/mysql \
  mysql:8

A few months later you upgrade Podman from 4.3 to 5.0.
The new binary rewrites the storage layout and removes ~/.local/share/containers/storage/volumes/db-data.
Your database data is gone.

The real trick is to keep the data outside the default storage tree so upgrades leave it untouched.


Step 1 – Create a Dedicated Volume Directory

Pick a spot outside the default path. A common choice is a subfolder of your home:

mkdir -p ~/podman-volumes
chmod 700 ~/podman-volumes

700 keeps the directory private—a quick security win.


Step 2 – Use --mount Instead of -v

-v is convenient but always creates a volume in the default tree.
--mount lets you point to any host path:

podman run -d --name mydb \
  --mount type=bind,source=$HOME/podman-volumes/db-data,target=/var/lib/mysql \
  mysql:8

Now the MySQL data lives in ~/podman-volumes/db-data, safe from Podman’s internal rewrites.


Step 3 – Persist the Mount Across Upgrades

Because the mount is defined by a host path, it survives upgrades.
Just make sure the directory exists before you start the container.
A tiny wrapper script does the trick:

#!/usr/bin/env bash
VOL=$HOME/podman-volumes/db-data
mkdir -p "$VOL"
podman run -d --name mydb \
  --mount type=bind,source="$VOL",target=/var/lib/mysql \
  mysql:8

Make it executable and use it instead of the raw podman run.


Step 4 – Back Up the Volume

Even with a stable location, backups are a must.
The simplest way is tar:

tar czf ~/backups/db-data-$(date +%F).tar.gz -C $HOME/podman-volumes db-data

Restore with:

tar xzf ~/backups/db-data-2026-11-01.tar.gz -C $HOME/podman-volumes

If your database has hot‑backup tools, use those instead.


Trade‑offs and Caveats

Approach Pros Cons
Default rootless volume (-v) Quick, no extra config Vulnerable to storage rewrites on upgrade
Bind mount (--mount type=bind) Data stays where you want it Requires manual path management
External storage driver (e.g., overlay2 on a separate partition) Isolated from home directory More complex, needs root
podman volume create --opt type=tmpfs Fast, no disk usage Data lost on reboot, not persistent

For most homelab users, the bind‑mount method is the sweet spot: it keeps data safe, stays rootless, and is easy to script.


Security Note

Binding a host directory into a container gives the container full access to that directory.
If you’re pulling untrusted images, consider:

  • Adding :ro (read‑only) to the mount.
  • Running the container as a dedicated user.
podman run -d --name mydb \
  --mount type=bind,source="$VOL",target=/var/lib/mysql,readonly \
  --user 1000:1000 \
  mysql:8

Common Pitfalls

Symptom Likely Cause Fix
Container fails to start with “permission denied” Host directory permissions too open chmod 700 on the host dir
Data disappears after upgrade Using -v instead of bind mount Switch to --mount
Container cannot write to volume Volume mounted read‑only Remove :ro or use writable bind
Podman complains “storage driver not supported” Upgraded to a driver that requires root Use overlay2 on a separate partition or keep using vfs

Automating with systemd‑User Units

If you like systemd, a systemd‑user unit keeps the container configuration in one place and restarts it automatically.

# /etc/systemd/user/mydb.service
[Unit]
Description=MyDB Container
After=podman.service

[Service]
ExecStart=/usr/bin/podman run --rm --name mydb \
  --mount type=bind,source=$HOME/podman-volumes/db-data,target=/var/lib/mysql \
  mysql:8
ExecStop=/usr/bin/podman stop -t 10 mydb
Restart=on-failure

[Install]
WantedBy=default.target

Enable it with:

systemctl --user enable --now mydb.service

When to Use a Dedicated Storage Driver

If you’re running a production‑grade database that needs high performance, you might move the storage driver to a separate partition. That requires root and a bit more setup:

sudo mkdir -p /var/lib/podman
sudo chown $USER:$USER /var/lib/podman
sudo podman system reset

Edit /etc/containers/storage.conf to set graphroot to /var/lib/podman.
This isolates Podman’s storage from your home directory entirely, but it breaks the pure rootless model. Weigh the trade‑offs.


Quick Reference Commands

# Create a dedicated volume dir
mkdir -p ~/podman-volumes && chmod 700 ~/podman-volumes

# Run a container with a bind mount
podman run -d --name mydb \
  --mount type=bind,source=$HOME/podman-volumes/db-data,target=/var/lib/mysql \
  mysql:8

# Backup the volume
tar czf ~/backups/db-data-$(date +%F).tar.gz -C $HOME/podman-volumes db-data

# Restore the volume
tar xzf ~/backups/db-data-2026-11-01.tar.gz -C $HOME/podman-volumes

Rootless Podman is a great way to keep containers safe and lightweight, but it does bring a subtle upgrade risk for volumes.
By moving your data to a dedicated bind mount, scripting the setup, and backing up regularly, you can keep your data intact no matter how many times you upgrade Podman or your distro. For most homelab users, this approach strikes the right balance of simplicity, security, and reliability.


See also