Skip to content

Raspberry Pi OS Trixie Migration Guide: Safe Upgrade from Bookworm

Raspberry Pi OS Trixie is the current major Raspberry Pi OS release. A major OS upgrade is a good time to remove configuration drift, but it can interrupt a home server if Docker volumes, SSH keys, or systemd services are left behind.

This guide uses the safe route: inventory the old Bookworm installation, back up the data that matters, install a fresh Trixie image, and restore services one at a time. Raspberry Pi recommends a new image rather than an in-place major-version upgrade.

What to plan for

Use this guide on Raspberry Pi 4, Raspberry Pi 5, or a compatible Compute Module. Do not overwrite the old boot disk until the new system has booted and your services have been tested. Keeping it unchanged is the simplest rollback plan.

  • Desktop systems use Wayland by default; older X11-only remote-desktop workflows may need adjustment.
  • Python applications should use a virtual environment instead of global pip installs.
  • Camera commands are named rpicam-*; legacy raspivid and raspistill are unsupported.
  • Test unattended scripts that use sudo after the migration.

1. Inventory the old system

Connect by SSH or use a local terminal, then save an inventory outside the boot disk. Replace /media/backup with a mounted USB disk or network share.

1
2
3
4
5
6
7
mkdir -p /media/backup/pi-migration
hostnamectl > /media/backup/pi-migration/hostnamectl.txt
uname -a > /media/backup/pi-migration/kernel.txt
dpkg-query -W -f='${binary:Package}\n' | sort > /media/backup/pi-migration/packages.txt
systemctl list-unit-files --state=enabled > /media/backup/pi-migration/enabled-services.txt
crontab -l > /media/backup/pi-migration/user-crontab.txt 2>/dev/null || true
sudo crontab -l > /media/backup/pi-migration/root-crontab.txt 2>/dev/null || true

For a Docker host, record containers, volumes, and Compose files:

1
2
3
4
docker ps -a > /media/backup/pi-migration/docker-containers.txt
docker volume ls > /media/backup/pi-migration/docker-volumes.txt
find "$HOME" /opt /srv \( -name compose.yaml -o -name docker-compose.yml \) 2>/dev/null \
  > /media/backup/pi-migration/compose-files.txt

The package list is a reference, not an instruction to reinstall everything. Reinstall only the applications you still need.

2. Back up configuration and data

Back up data deliberately. A copy of /etc is useful for comparison, but restoring it wholesale can overwrite Trixie defaults.

1
2
3
4
backup=/media/backup/pi-migration
sudo tar --xattrs --acls -czf "$backup/etc.tar.gz" /etc
tar -czf "$backup/home-config.tar.gz" "$HOME/.ssh" "$HOME/.config" 2>/dev/null
sudo tar -czf "$backup/srv-opt.tar.gz" /srv /opt 2>/dev/null

For a Docker Compose project, stop it briefly and archive its bind-mounted data. Database-backed services also need a logical export; a copy of a live database directory is not reliable.

1
2
3
4
5
6
7
# PostgreSQL example
docker compose exec -T postgres pg_dumpall -U postgres \
  > /media/backup/pi-migration/postgres.sql

# MariaDB/MySQL example
docker compose exec -T mariadb mariadb-dump -u root -p --all-databases \
  > /media/backup/pi-migration/mariadb.sql

Keep private keys and tokens only on an encrypted, physically controlled backup drive.

3. Install a clean Trixie image

  1. Use Raspberry Pi Imager to write current Raspberry Pi OS (64-bit) to a different disk where possible.
  2. In the Imager customisation screen, set a hostname, user, Wi-Fi settings if needed, and enable SSH.
  3. Boot the new disk and verify that SSH works before taking the old service offline.
  4. Update the new system:
1
2
3
sudo apt update
sudo apt full-upgrade -y
sudo reboot

For Pi 5 NVMe boot, verify firmware, boot order, HAT, and power supply with the NVMe boot guide. Do not copy the old /boot/firmware/config.txt without reviewing each setting.

4. Restore access first

Restore SSH public-key access before workloads. Copy only the required files, then confirm a second terminal can log in:

1
2
3
4
mkdir -p ~/.ssh
chmod 700 ~/.ssh
# Copy authorized_keys from the protected backup.
chmod 600 ~/.ssh/authorized_keys

For remote administration, configure Tailscale or Raspberry Pi Connect after the base system is stable.

5. Rebuild Docker services

Restore each Compose project separately. This makes an image, port, or permission problem easy to isolate.

sudo usermod -aG docker "$USER"
# Log out and back in for the group membership to apply.

mkdir -p ~/services
cp -a /media/backup/pi-migration/your-project ~/services/
cd ~/services/your-project
docker compose pull
docker compose up -d
docker compose ps
docker compose logs --tail=100

Restore database dumps only after their destination container is healthy. For related setups, see Docker Compose and Nginx Proxy Manager and the monitoring stack guide.

6. Recreate services, schedules, and Python environments

Compare old systemd units with the new defaults instead of copying all of /etc/systemd:

1
2
3
4
sudo install -m 644 /media/backup/pi-migration/my-app.service /etc/systemd/system/my-app.service
sudo systemctl daemon-reload
sudo systemctl enable --now my-app.service
journalctl -u my-app.service -b --no-pager

Confirm the service user, paths, environment files, and group permissions. The systemd daemon guide covers reliable units.

Recreate, rather than copy, virtual environments:

1
2
3
4
5
6
sudo apt install -y python3-venv
cd ~/services/my-python-app
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
pip install -r requirements.txt

Final checklist

  • SSH key login and local-console login work.
  • findmnt / shows the intended boot disk.
  • Docker data and database exports have been restored and tested.
  • Enabled services and scheduled jobs survive a reboot.
  • VPN, DNS, and remote-access services work from outside the LAN.
  • The old disk remains untouched until several successful new backups complete.

A clean migration takes more care than an in-place upgrade, but leaves the Pi easier to maintain and recover.