Running Docker apps at home or on a VPS feels low-risk until you try to upgrade and discover your backup is too old to bridge the gap — and you are staring at a broken stack with no clean path forward.
Why upgrades break without checkpoints
Most self-hosted apps handle schema migrations internally on first boot after an upgrade. That works fine when you move one version at a time. It stops working when you skip too many releases, because migration scripts are often written to assume the previous version's schema, not a version from two years ago.
Home Assistant is a clear example. If you have a Docker install from 2022 and your latest backup is equally old, moving straight to the current release risks corrupting HACS extensions and Zigbee device state. The backup exists, but it cannot be applied to the new version without first walking through intermediate releases. That is not a bug — it is how incremental migration works. The gap is the problem.
The same pattern appears with Nextcloud, Immich, and almost any app that manages its own database. Nextcloud explicitly documents major-version upgrade paths and warns against skipping them. Immich has had breaking changes between minor versions during rapid development phases. Navidrome stores a SQLite database that can accumulate structural assumptions. When you skip checkpoints, you are betting that no migration script along the way required the previous step.
The Proxmox helper-script trap
Proxmox helper scripts make it easy to spin up containers for Immich, Nextcloud, Navidrome, and Crafty with a single command. That convenience creates a different problem: the scripts configure things for you, and if you did not read the output carefully, you may not know where credentials were written or how Tailscale was set up inside the container.
A common scenario: a Proxmox user loses access to the PVE web UI and cannot locate generated Crafty credentials. The Tailscale node inside the container is not reachable because the VM's network configuration changed. The container is running, but access to it is effectively lost. This is not a disaster on its own — it becomes one when you also need to upgrade the app inside that container, because the upgrade path starts with having a known-good backup and confirmed access.
Before running any helper script, write down the container ID, note where credentials were printed, confirm Tailscale connectivity, and take a Proxmox snapshot immediately after first login. That snapshot is your checkpoint zero.
Planning checkpoints for a growing homelab stack
A new homelab operator with NPM, Portainer, Jellyfin, Vaultwarden, Tailscale, and arr apps running already faces a real architectural question when adding Immich: how do I upgrade any of this in six months without pain?
The answer is checkpoints built into your routine, not patched in after the fact.
Pin your image tags. Running image: immich-server:latest in your Compose file means every docker compose pull pulls whatever the maintainers released today. If a breaking change ships, you find out the hard way. Pin to a specific version tag (v1.106.1) and upgrade deliberately. When you are ready to upgrade, check the release notes for each version between your current tag and the target. If the project calls out a required intermediate step, do it.
Take volume backups before pulling new images. The pattern is simple: stop the container, back up its data volume, pull the new image, start the container, verify the app loads and your data is intact. If verification fails, restore the volume and roll back to the previous image tag. This is especially important for database-backed apps like Immich, Nextcloud, and Vaultwarden.
Document your current versions. A simple text file or a note in your homelab wiki with current image tags and the date you last upgraded is enough. You do not need a sophisticated system — you need to avoid the situation where you cannot remember what version you are on. Tools like ServerCompass let you see all your running services at a glance, which makes it easier to audit what is deployed and catch apps that have drifted far behind current releases.
Test your backups. A backup that has never been restored is a backup you cannot trust. Periodically do a test restore into a scratch container on a non-production network. For Vaultwarden, this is especially worth doing — your password vault is not a good place to discover that restores fail.
What to do if you are already stuck
If you are in the situation where your Home Assistant backup is too old to cleanly restore to the current release, or your Proxmox container is running but inaccessible, the path forward is methodical.
For version-gap upgrades: find the release history for your app and identify intermediate versions. Pull each intermediate image tag, start the container, let it run migrations, verify, stop, then move to the next step. Do not skip steps even if the app appears to start — the migration may have partially completed.
For lost credentials: check the helper script's source or the project's documentation for default credential locations. For Crafty, credentials are typically written to a file inside the container at first boot. If the container is still running, docker exec into it to retrieve them. If the container is gone, restore from your most recent snapshot.
For broken Tailscale access inside a VM: log into the Tailscale admin console, find the stale node, remove it, then re-authenticate from inside the container. If you cannot get into the container, use the host's console access (Proxmox web UI or VNC) rather than Tailscale.
Checklist
- Pin Docker image tags to specific versions in your Compose files; never rely on
latestfor production services - Before every upgrade, stop the container, back up its data volume, then pull the new image
- Check release notes for each version between your current tag and target — note any required intermediate stops
- Take a Proxmox snapshot immediately after spinning up a new container via helper script
- Write down generated credentials and Tailscale node names before closing the terminal
- Keep a simple record of current image versions and last-upgraded dates for each service
- Test a backup restore into a scratch container at least once per service before you need it in an emergency
- Use a service inventory tool like ServerCompass to keep visibility over what is running and catch apps that have fallen far behind
