DiyMediaServer
Featured image of post How to Update a Jellyfin Your Server to 12.1 Without Breaking It

How to Update a Jellyfin Your Server to 12.1 Without Breaking It

How to update a Jellyfin server to 12.1 safely: back up first, test the one-way migration, and avoid the plugin issues.

The usual advice on how to update a Jellyfin server fits on one line: add the repo, run apt upgrade, restart. For 10.x point releases that was fine for the most part. In the case of Jellyfin 12 it’s how you find out the database migration is one-way, after it has already run, and you didn’t take a backup first.

Jellyfin 12 rewrites the database on its first run. Reinstalling the old 10.x package won’t bring it back. And I stacked a second change on top of it: my Jellyfin container was the last Ubuntu guest in a lab that’s otherwise all Debian, so I rebuilt it on Debian 13 instead of upgrading it in place. Two migrations, one outage window, one wife who notices when the TV app stops working.

Here’s what I did, what broke, and the traps you’ll hit if you follow the same path.

๐Ÿ’ญ
TL;DR: I skipped Jellyfin 12.0 for production, tested the one-way 10.11 to 12 migration on a throwaway Debian 13 LXC, and cut over to 12.1 on a fresh Debian 13 LXC. Test first: Debian’s group IDs, the missing intel-opencl-icd, plugin compatibility, and a misbehaving fail2ban jail all surfaced in testing instead of in production.

Know what this post covers before you commit to it. It’s a Proxmox unprivileged LXC, an Intel iGPU, and the apt packages. If you run Jellyfin in Docker or on bare metal, the backup, plugin, migration and library-scan steps carry over as written. The render GID, OpenCL and idmap sections don’t apply to you, and you can skip them.

How to Update a Jellyfin Server to 12.x: The Short Version

Here’s the safe path. Everything after this list is the detail, and the war stories from when a check failed.

  1. Get to Jellyfin 10.10.7 or any 10.11.x release first. From there, 12.x is a direct upgrade.
  2. Stop Jellyfin and back up /var/lib/jellyfin and /etc/jellyfin (or the Docker config volume). Test your backup.
  3. Remove third-party plugins. Builds made for 10.11 won’t load on 12.
  4. Restore that backup into a throwaway test container, and run the whole upgrade there first.
  5. Run the migration and don’t interrupt it. It can be slow, but it is running.
  6. Run a full library scan. 12.x requires one.
  7. Reinstall plugins one at a time, restarting between each.
  8. Keep the old install (or its backup) untouched until the people using the server confirm it works.

If you’re on Docker, check which image you pinned before you pull anything.

Why I Skipped Jellyfin 12.0 and Waited for 12.1

Jellyfin 12.0 was released on 2026-09-08. I waited for the first point release, because that’s where the launch-week bugs get fixed after somebody else reports them. Is that selfish? Yes. Does my wife care? Not even slightly.

If a package downgrade can’t undo a change, I want a point release and my own testing before my production server uses it. Waiting cost me about a week: 12.1 landed in the Debian trixie repository on 2026-09-15. This rule is mine, not Jellyfin’s. If you run Jellyfin for nobody but yourself and you’ve got a tested restore, go be the early adopter.

Why I Rebuilt on Debian 13 Instead of Upgrading Ubuntu in Place

My Jellyfin container was the last Ubuntu LXC in a lab that’s otherwise all Debian (I’ve covered the distro question in Debian vs Ubuntu: choosing the right Linux distro). Every lab-wide change had become “do it everywhere, then do it differently on Jellyfin.” A major upgrade that already demanded a backup, testing, and an outage was the obvious moment to stop paying the one-off Ubuntu tax.

Rebuilding instead of upgrading in place also gave me a free rollback. The old container stayed intact and powered off while the new one proved itself. You don’t get that with do-release-upgrade.

Intelยฎ Coreโ„ข i5-14500 14th Generation Desktop Processor
Intelยฎ Coreโ„ข i5-14500 14th Generation Desktop Processor. A 14-core (6 P-cores plus 8 E-cores), 20-thread Raptor Lake Refresh CPU that turbos to 5.0 GHz, with the same UHD 770 graphics and Quick Sync engine that make Jellyfin and Plex hardware transcoding cheap. Ideal for Proxmox homelabs and everyday desktops when you want snappy VM/container workloads without needing a discrete GPU.
Amazon Price: Loading...
Availability: Checking...
Contains affiliate links. I may earn a commission at no cost to you.

Back Up Before the One-Way Database Migration

Stop Jellyfin before you back it up. A live SQLite database copied mid-write isn’t a backup. It’s a hope.

On Proxmox, the easy answer is a stop-mode backup of the whole container to Proxmox Backup Server. That’s what my test container restored from: a scheduled stop-mode PBS snapshot, with jellyfin.db cleanly checkpointed. If you’d rather have a plain archive you can read without PBS, do it from inside the container:

systemctl stop jellyfin
systemctl status jellyfin --no-pager   # confirm it's actually stopped

tar -C /var/lib -czf /root/jellyfin-data-before-12.tar.gz jellyfin
tar -C /etc -czf /root/jellyfin-config-before-12.tar.gz jellyfin

# prove the archives are readable before you trust them
tar -tzf /root/jellyfin-data-before-12.tar.gz > /dev/null && echo data-ok
tar -tzf /root/jellyfin-config-before-12.tar.gz > /dev/null && echo config-ok

Copy those off the container. Also save dpkg-query -W, systemctl cat jellyfin, and your fail2ban files, because you’ll want to reference them later.

You don’t need to back up the media itself if it lives on separate storage and Jellyfin mounts it read-only. Mine comes in as three read-only binds from an NFS export, so Jellyfin couldn’t damage it if it tried. The thing you’re protecting is Jellyfin’s state: database, metadata, users, watch history, scheduled tasks. Mine was a 417 MiB jellyfin.db, plus about 37 GiB of metadata and images under /var/lib/jellyfin.

A backup you’ve never restored is not a backup. The test below is also your restore test. Use it.

WD 14TB Elements Desktop External Hard Drive
WD 14TB Elements Desktop External Hard Drive. A desktop external drive that packs 14 TB into a USB 3.0 enclosure, making it one of the cheapest ways to add bulk storage to a homelab or grab a large drive for shucking into a NAS. WD’s CMR recording on these capacities means solid sustained write speeds, and the wide compatibility with Windows, Mac, and Linux makes it an instant-plug backup target.
Amazon Price: Loading...
Availability: Checking...
Contains affiliate links. I may earn a commission at no cost to you.

Test the Jellyfin 12 Migration on a Throwaway LXC

The testing container was an unprivileged Debian 13 LXC at 192.168.1.18: 8 cores, 8 GB of RAM, 200 GB thin-provisioned, nesting=1, the same three read-only media binds and the same GPU passthrough as the production server. It got Jellyfin 12.1 from the official trixie repo. Its whole purpose was to absorb my mistakes.

It absorbed a lot of them.

Cut the test off from the internet

Give the throwaway container a gateway long enough to install packages, then take it away. Once package work was done, I removed its default route. On-subnet traffic still worked (NFS to the storage VM, DNS to my resolvers, SSH from my controller), but nothing could leave the LAN.

Why? Because that container holds a copy of your real users, real watch history, and real plugin state. You don’t want a test Jellyfin box reaching out to update plugins behind your back or pushing scrobbles from test playback. And you really don’t want two Jellyfin servers with the same identity both talking to the outside world.

Install Jellyfin masked, then restore

Mask the service before you install the package, so apt can’t start a fresh Jellyfin that initializes an empty database on top of where your restore is about to land:

systemctl mask jellyfin
apt install --no-install-recommends jellyfin

Then restore your 10.11 state into it. Two details here cost real time in testing.

First, jellyfin-server ships three conf files, and one is easy to miss:

/etc/default/jellyfin
/etc/jellyfin/logging.json
/etc/systemd/system/jellyfin.service.d/jellyfin.service.conf

logging.json lives inside /etc/jellyfin, the directory you’re about to overwrite. Restore that directory and you’ve replaced a Debian package-owned file with an Ubuntu one. Restore /etc/jellyfin per child and leave the package’s logging.json alone:

tar -C /etc -xzf /root/jellyfin-config-before-12.tar.gz --exclude='jellyfin/logging.json'
tar -C /var/lib -xzf /root/jellyfin-data-before-12.tar.gz
dpkg -V jellyfin-server   # no output means the conf files are untouched

Second, don’t pass --numeric-owner when the old and new containers might assign different numeric IDs to the jellyfin account. Extracting as root, GNU tar maps owners by name. Then check nothing slipped through:

find /var/lib/jellyfin /etc/jellyfin ! -user jellyfin -ls | head

While you’re in there, leave the zero-byte .jellyfin-* files alone. Jellyfin writes markers like /var/lib/jellyfin/plugins/.jellyfin-plugin and /etc/jellyfin/.jellyfin-config into each directory it manages, and it refuses to start if it finds the wrong marker in the wrong place. They look like junk. They aren’t.

Hold the plugins back

The 12.0 release notes are clear about this: remove third-party plugins before upgrading, because plugins built for 10.11 won’t load on 12 and need updated builds from their maintainers. I moved every legacy plugin directory into a root-only quarantine outside Jellyfin’s directory, left the .jellyfin-plugin marker in place, and let 12.1 start with zero third-party plugins loaded:

mkdir -m 700 /root/plugin-quarantine
find /var/lib/jellyfin/plugins -mindepth 1 -maxdepth 1 -type d ! -name configurations \
  -exec mv -t /root/plugin-quarantine {} +

The Debian 13 Render GID Trap: Your GPU Goes to Postfix

This is the one that would’ve hurt. And nothing static would’ve caught it.

An unprivileged LXC reaches the host GPU through lxc.idmap lines that punch a hole in the ID shift for the render group. (If idmaps are new to you, start with my UID/GID mapping guide and the Quick Sync in unprivileged LXC write-up.) My old Ubuntu container used this set, and the new one uses it too once Postfix is out of the way:

lxc.idmap: u 0 100000 1000
lxc.idmap: u 1000 1000 1
lxc.idmap: u 1001 101001 64535
lxc.idmap: g 0 100000 104
lxc.idmap: g 104 104 1
lxc.idmap: g 105 100105 896
lxc.idmap: g 1001 1001 1
lxc.idmap: g 1002 101002 64534
lxc.mount.entry: /dev/dri/ dev/dri/ none bind,optional,create=dir
lxc.cgroup2.devices.allow: c 226:128 rwm
lxc.cgroup2.devices.allow: c 226:0 rwm

The important line is g 104 104 1. On my Proxmox host, /dev/dri/renderD128 is root:render, and render is GID 104. Ubuntu happens to allocate render at 104 inside the container too. So container 104 maps to host 104, Jellyfin’s render group owns the GPU, and everything works. By coincidence.

Here’s what testing found on a stock Debian 13 container:

GroupProxmox hostUbuntu 26.04 CTDebian 13 CT (stock)
render104104992
video444444
GID 104 belongs torenderrenderpostdrop

Debian allocates render dynamically from the top of the system range (992 on my build) and puts postdrop, Postfix’s setgid group, at 104. Copy this without dealing with Postfix and you’ve handed the host’s GPU group to the container’s mail system. Jellyfin’s real render group gets nothing.

You’d see “hardware transcoding doesn’t work.” The actual problem is a privilege assigned to the wrong group. The idmap is textually correct. What changed underneath it is Debian’s group numbering, and that never shows up in a diff.

GMKtec Mini PC i7-1185G7
GMKtec Mini PC i7-1185G7. A compact quad-core mini PC built on the Intel Core i7-1185G7, shipping with 16 GB of DDR4 and a 1 TB SSD. Iris Xe graphics bring Quick Sync along for hardware transcoding, and the small footprint suits a Proxmox node running a handful of VMs and LXC containers rather than a dense cluster.
Amazon Price: Loading...
Availability: Checking...
Contains affiliate links. I may earn a commission at no cost to you.

Align the guest to the host, not the idmap to the guest

The tempting fix is to change the idmap to g 992 104 1. Don’t. That 992 is dynamically allocated. The next Debian build could land somewhere else, and then your testing and production containers differ in a way you never tested.

Instead, move the container’s groups to match the contract: render at 104 and a media group at 1001 for the library. A Jellyfin container has no use for a local mail server, so the cleanest way to free GID 104 is to remove Postfix and its group. Do it before the custom idmap is installed. Under the default map, a guest-side file owned by GID 104 sits at host GID 100104, which isn’t what you want.

โš ๏ธ
Warning: Only do this on a freshly built container, before Jellyfin or your restore exist on it. On an older container, other files may already be owned by GID 104 or render’s old GID, and renumbering groups will quietly hand them to the wrong owner. Snapshot first (pct snapshot <ctid> pre-gid on the host, or a vzdump <ctid> --mode stop backup if your storage can’t snapshot), so a mistake is a rollback instead of an afternoon of forensics.
apt purge postfix
getent group postdrop && groupdel postdrop

# nothing should own GID 104 now; stop if this prints anything
find / -xdev -gid 104 -ls

groupmod -g 104 render
groupadd -g 1001 media

If you do want local mail on this container (cron output, unattended-upgrades reports), don’t purge Postfix. Move postdrop to a free GID instead, and remember that chgrp clears the setgid bit on /usr/sbin/postdrop and /usr/sbin/postqueue. Put both back to mode 2555 afterward or local mail stops without an error.

With the groups aligned, create the jellyfin account before the package does, enroll it in video, render and media, install the idmap, and stop/start the container once to activate it. On my production container the result for id jellyfin was:

uid=102(jellyfin) gid=105(jellyfin) groups=105(jellyfin),44(video),104(render),1001(media)

The commands to create the account with these IDs and groups (check first that UID 102 and GID 105 are free; both getent lines should print nothing):

getent passwd 102; getent group 105
groupadd -g 105 jellyfin
useradd -u 102 -g 105 -G 44,104,1001 -d /var/lib/jellyfin -s /usr/sbin/nologin jellyfin

render at 104, matching the host. That’s the whole point.

Prove it with an open, not an ls

ls -l /dev/dri showing render is encouraging. It isn’t proof. Open the device as the service account:

runuser -u jellyfin -- python3 -c "import os; print(os.open('/dev/dri/renderD128', os.O_RDWR))"

A file descriptor number means Jellyfin can use the GPU. Anything else means it can’t, no matter what the dashboard says.

And don’t panic when vainfo fails as container root with “Failed to open the given device!” Container root maps to host UID 100000, which isn’t the device owner and isn’t in render. Only jellyfin has access.

Without runuser -u jellyfin, the same command fails:

python3 -c "import os; print(os.open('/dev/dri/renderD128', os.O_RDWR))"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
    import os; print(os.open('/dev/dri/renderD128', os.O_RDWR))

PermissionError: [Errno 13] Permission denied: '/dev/dri/renderD128'
Intel NUC 12 Pro (NUC12WSHi5)
Intel NUC 12 Pro (NUC12WSHi5). A compact “Wall Street Canyon” mini PC with a 12th-gen Core i5-1240P and Iris Xe that can drive up to four displays (dual Thunderbolt 4 + dual HDMI), plus 2.5GbE and Wi-Fi 6E. The H-chassis adds a 2.5โ€ณ bay alongside NVMe storage and up to 64GB RAM, making it a quiet, versatile homelab node or HTPC/office box.
Amazon Price: Loading...
Availability: Checking...
Contains affiliate links. I may earn a commission at no cost to you.

No intel-opencl-icd on Debian 13: What Happens to HDR Tone Mapping

My old Ubuntu container had intel-opencl-icd installed, and Jellyfin’s OpenCL tone mapping used it. I assumed I’d install the same package on Debian 13.

You can’t. The intel-compute-runtime tracker page shows it in Debian 11, Debian 12 and testing, and nothing for trixie. Intel’s graphics compiler still wants LLVM 14, which trixie doesn’t ship. Jellyfin’s own Intel hardware acceleration docs call out the same gap and point at Intel’s compute-runtime releases instead.

OpenCL isn’t the only road, though. Intel’s VPP tone mapping runs through VA-API, which Debian 13 has (intel-media-va-driver 25.2.3). In testing, a client-driven playback of a 2160p HDR10+ HEVC file got transcoded to 1440p with tonemap_vaapi and hevc_qsv, at 48 fps, 2x realtime, with zero software fallback. The output frames matched what the old Ubuntu server produced.

So VPP works, and my production server still has HDR-to-SDR tone mapping turned off. The only OpenCL driver Debian 13 offers (Mesa’s) needed more than this container has to give, and I’d rather leave this feature off than enable it and have to troubleshoot when someone texts me to say it isn’t working. Quick Sync stays on. Ordinary hardware transcodes and Direct Play work.

If you test this yourself, use an actual HDR file. A successful H.264 transcode proves nothing about HDR. And check the output for HDR metadata, because a transcode that strips the mastering-display data without really tone mapping “passes” and still looks washed out.

How to Update a Jellyfin LXC to 12.1: The Cutover

Once the testing passed, production was mostly a matter of doing the same thing again without improvising. Here’s the order I used:

  1. Build the new Debian 13 container on a temporary IP (mine was 192.168.1.17) with the aligned groups, the idmap, the media binds, and Jellyfin 12.1 installed but masked.
  2. Stop Jellyfin on the old container and take a final stop-mode backup.
  3. Restore that final state into the new container: /var/lib/jellyfin in full, /etc/jellyfin per child, plugins quarantined.
  4. Run the database migration and let it finish.
  5. Run a full library scan. Jellyfin requires one after the 12.x migration because alternate versions are stored differently, and some items may briefly look newly added.
  6. Reinstall plugins one at a time.
  7. Move the new container to the old container’s IP (192.168.1.4 for me) so the reverse proxy and every client config keep working unchanged.
  8. Re-enable fail2ban and test it with a real ban.
  9. Leave the old container stopped, untouched, and backed up.

On step 4: the migration runs on the first start, and it can take a while on a large library. Watch it with journalctl -u jellyfin -f and don’t kill it because it’s slow. The release notes are explicit that you shouldn’t stop the server mid-migration. Jellyfin 12 also has a dedicated mode, --mode MigrateSystem, that performs the migration and exits before the server starts serving. I ran the migration as its own step that way, so the “did the database survive” question got answered before any client could connect. If you do the same, run it as the jellyfin user with the same data, config, cache and log paths the service uses (they’re in /etc/default/jellyfin). Run it as root and you’ll get root-owned files the service can’t write.

Step 7 is why I bothered with a temporary IP. Swapping addresses meant the reverse proxy, clients, and every app that talks to Jellyfin needed no edits. Afterward I rebooted the new container on purpose and checked that the binds, the GPU, Jellyfin, fail2ban and client playback all came back with nobody touching anything.

Jellyfin 12 Plugins: Intro Skipper, WeTrakr and File Transformation

Plugins went back one at a time, with a restart and a log check between each. That’s tedious. It’s also the only way to know which plugin broke startup when one does.

Here’s how mine landed:

  • Intro Skipper 12.0.4.0. Installed by hand from a hash-verified artifact. It targets ABI 12.0.0.0 and runs fine on the 12.1 server. Its meta.json sets "autoUpdate": true, so on a container with internet access Jellyfin can swap your verified build for whatever the repository is serving. I re-hashed the DLL after the first normal start to confirm it hadn’t changed underneath me.
  • WeTrakr. Installed from its manifest, with a brand-new configuration created on the new server. I didn’t copy the old config, which held a webhook token. (If you’re still on Trakt and wondering about WeTrakr, I wrote up my Trakt to WeTrakr move.)
  • File Transformation 3.0.1.0. Kept, with its repository still enabled, so it isn’t permanently pinned. I’ll watch it.

Check that every plugin you run has a repository that can actually supply it. Production was running at least one that none of its declared repositories offered. A plugin without a repository has no in-product update path, and you won’t find out until it needs one.

If a plugin stops Jellyfin from starting, stop the service, move that plugin’s directory out of /var/lib/jellyfin/plugins, and start again. If it loads but misbehaves, check whether its maintainer has published a 12.x build. If the only compatible build is in Jellyfin’s unstable plugin repository, that’s fine for testing, but write down that production now depends on a pre-release.

The Dashboard Restart That Doesn’t Come Back

After the cutover, I changed a setting, clicked restart in the Dashboard, and Jellyfin went away. It stayed away.

The packaged unit uses Restart=on-failure. A Dashboard-requested restart makes Jellyfin exit cleanly, with status 0. systemd looks at a clean exit, concludes nothing failed, and correctly leaves the service stopped. Everyone did their job. Nobody restarted Jellyfin.

You’ll restart the service from the shell, it’ll come back, and you’ll blame a fluke. Then it’ll happen again the next time someone uses the Dashboard. The fix is a drop-in that restarts on any exit:

mkdir -p /etc/systemd/system/jellyfin.service.d
cat > /etc/systemd/system/jellyfin.service.d/90-restart-clean-exit.conf <<'CONF'
# Jellyfin's Dashboard restart exits with status 0.
[Service]
Restart=always
RestartSec=5s
CONF
systemctl daemon-reload
systemctl show jellyfin -p Restart

Use your own filename. Don’t edit jellyfin.service.conf in that directory, because it’s one of the three package conf files and the next upgrade will want to talk to you about it.

Restart= doesn’t cover reboots. My test container came back disabled after unmasking, so check systemctl is-enabled jellyfin after you unmask.

fail2ban: My Jail Had Been Banning Port 22

Testing was the first time I drove a real ban against my Jellyfin jail end to end. fail2ban banned the test address in about a second, my phone buzzed, and then I read the firewall rule back:

tcp dport 22 ip saddr @addr-set-jellyfin reject with icmp port-unreachable

Port 22. The jail declared port = 8096,8920, but the action was a bare nftables[type=multiport], so it fell back to the action’s default of port = ssh. Brute-forcers got banned from a port they weren’t using, and I got a notification telling me I’d won. For over a year.

That exact line is in my own fail2ban for Jellyfin guide, which now has the fix and a way to test it. The short version is one line:

action   = nftables[type=multiport, port="%(port)s", protocol="%(protocol)s"]

Then confirm what fail2ban actually loaded with fail2ban-client get jellyfin action nftables port. You want 8096,8920. The existing filter matched Jellyfin 12’s denial messages unchanged.

Frequently Asked Questions

โžค Can I upgrade directly from Jellyfin 10.11 to 12.1?
Yes. Jellyfin supports a direct upgrade from any 10.11.x release to 12.x, with no intermediate version. Servers older than 10.10.7 must reach 10.10.7 first. The catch is that the database migration is one-way, so take a full stopped backup of /var/lib/jellyfin and /etc/jellyfin before the first 12.x start.
โžค Can I roll back from Jellyfin 12 to 10.11?
Not by reinstalling the old package. Jellyfin 12 rewrites the database on first start, and 10.11 can’t use the result. Rolling back means restoring your pre-upgrade backup of the data and config directories, or switching back to an untouched old container. That’s why I kept the old container stopped and intact until the new server proved itself.
โžค Why does hardware transcoding fail after moving my Jellyfin LXC to Debian 13?
Usually the render GID. Ubuntu puts render at 104, matching the Proxmox host, while Debian 13 puts postdrop at 104 and render somewhere near 992. An idmap copied from Ubuntu then maps the host GPU group to Postfix. Align the container’s groups to the host before installing the idmap, then test with a real os.open() as the jellyfin user.
โžค How do I get HDR tone mapping working on Debian 13?
Not through intel-opencl-icd, because Debian 13 doesn’t ship it. Intel’s VPP tone mapping runs through VA-API and worked on my i5-12600K in testing, producing proper BT.709 output with hevc_qsv. I’ve left tone mapping disabled in production until I decide on it. Test with an actual HDR file, not an H.264 transcode.
โžค Why did Jellyfin stay stopped after a Dashboard restart?
A Dashboard restart makes Jellyfin exit with status 0, and the packaged unit uses Restart=on-failure, which treats a clean exit as intentional. Add a systemd drop-in with Restart=always and RestartSec=5s in its own file under /etc/systemd/system/jellyfin.service.d/, run systemctl daemon-reload, and test a Dashboard restart again.

What I’d Do Again, and What I’d Do Sooner

Waiting for 12.1 cost me a week and nothing else. Testing on a throwaway Debian 13 container cost me a lot more than a week, and it was worth every hour. Every serious problem in this post (GPU access going to Postfix, no OpenCL package, a fail2ban jail aimed at the wrong port, a service that didn’t come back) showed up on a container I was allowed to break. Production saw none of them.

Rebuilding on Debian 13 instead of upgrading Ubuntu in place retired every Ubuntu-only exception in one move. The lab is one distro now. The next lab-wide change gets tested once. (If your other containers still need the Debian 12 to 13 jump, I covered that in upgrading Debian 12 to 13 LXCs.)

What would I do sooner? Read back the fail2ban rule. Fourteen months of trusting a phone notification is a long time to be wrong.

So here’s how to update a Jellyfin server to 12 without a story like mine: take a stopped backup, prove you can restore it, and run the whole migration on a container you’re allowed to break. Wait for the point release. Always test.