This is a continuation of moving the private cloud to a mini PC. The cloud was still running OpenStack 2025.1, an older release. This post covers how I brought it up to the latest release, 2026.2.
Why keeping software updated matters
Updating isn’t only about new features. Each release stops getting security fixes after a while, so an old version keeps known vulnerabilities open. A private cloud is still a network service, so it needs the same care as any other server. Kolla-Ansible is also tied to specific OpenStack releases, so staying on a supported version keeps the deployment tools working. Small, regular updates are also easier than one large upgrade later.
⚠️ Warning: Read the release notes before every update, because a new release can change defaults and break things that worked before.
Why upgrade in several steps
OpenStack doesn’t support jumping over releases with Kolla-Ansible, the tool that deploys it. So the upgrade went through every release in between:
- 2025.1 to 2025.2
- 2025.2 to 2026.1
- 2026.1 to 2026.2
Each step had the same routine: back up, update the configuration, pull the new container images, run the upgrade, and check that everything still worked before moving on.
⚠️ Warning: Don’t skip releases. The upgrade tool is only tested one step at a time, so skipping one can break the cloud in ways that are hard to fix.
Backups first
The most important thing I wanted to protect was the Vaultwarden password database, which runs on the Kubernetes cluster. Velero already backs it up every day, so I took an extra backup right before each step and checked that it completed. Replace the names in angle brackets with your own values:
velero backup create <name> --from-schedule <schedule-name> --wait
velero backup describe <name> --details
I also saved a copy of the OpenStack database and the configuration files on the
same host before every step. The password comes from passwords.yml, and
MYSQL_PWD keeps it off the command line:
PW=$(grep -E "^database_password:" /etc/kolla/passwords.yml | sed -E "s/^database_password:[[:space:]]*//")
sudo docker exec -e MYSQL_PWD="$PW" mariadb mariadb-dump -uroot --all-databases \
--single-transaction --quick --routines --events --triggers --master-data=2 \
| gzip > all-databases.sql.gz
This wasn’t a full disaster-recovery plan, but it meant I could look back at the exact state if something went wrong.
🧠 Lesson learned: Check that a backup actually completed. A backup that runs without errors but never finishes is not a backup.
Configuration changes
Each release changes some defaults and removes some old settings. Most of the work was reading the release notes and updating the configuration to match:
- The message queue for Redis was replaced by Valkey, so the config had to be switched over before the upgrade.
- Unused settings and passwords from old releases were removed.
- The inventory file, which describes which services run where, was updated to match the new layout.
Each target release got its own virtual environment, so the previous one stayed available. Replace the names in angle brackets with the release you’re installing:
python3.13 -m venv ~/kolla-ansible/.venv-<release>
~/kolla-ansible/.venv-<release>/bin/pip install "kolla-ansible==<version>" "ansible-core>=<min>,<max>"
I checked each change with a dry run before applying the upgrade, so problems showed up early instead of in the middle of it:
kolla-ansible validate-config -i ./all-in-one
kolla-ansible prechecks -i ./all-in-one
💡 Tip: Kolla 22 and later warn about the
quay.io/openstack.kollaimages and stopprechecksunless you add--use-test-images. Those are the official release images, so the flag is safe for this step.pulldoesn’t accept it.
Running the upgrade
First I downloaded the new container images. This doesn’t change anything that’s running, so it’s safe to do ahead of time:
kolla-ansible pull -i ./all-in-one
Then I ran the upgrade in the background, so a dropped SSH session wouldn’t stop it. The PID file lets me check on it later:
nohup kolla-ansible upgrade -i ./all-in-one > upgrade.log 2>&1 < /dev/null &
echo $! > upgrade.pid
To check whether it’s still running, use the PID file and the log:
kill -0 "$(cat upgrade.pid)" && echo running || echo finished
tail -n 20 upgrade.log
🧠 Lesson learned: Don’t use
pgrep -f "kolla-ansible upgrade"to check. The pattern matches the command you’re running, so it always looks like the upgrade is still going.
After each upgrade I checked that every container was healthy and running the new image:
sudo docker ps --filter health=unhealthy
sudo docker ps --format "{{.Image}}" | sed "s/.*://" | sort | uniq -c
What changed for me
Most things worked without any change, but a few things surprised me:
Horizon moved to another port. The dashboard now answers on port 8080 instead of port 80, so bookmarks need updating.
The upgrade stopped partway through once. My check said it was still running when it had actually finished, which I only noticed after reading the log file carefully.
One backup service was already down. It was configured for a storage system I don’t run, so it had been failing long before this upgrade. I disabled it, which doesn’t affect the VMs or volumes.
Horizon login broke. Turning on the new message queue (Valkey) switched the dashboard’s login sessions to a setup that needs more than one node. With a single node, the login page failed until I pointed sessions back to memcached. I set
horizon_session_cache_backend: "memcached"inglobals.ymland ran:kolla-ansible reconfigure -i ./all-in-one -t horizonVMs restarting after a host reboot needed a setting that got lost. The fix now lives in an override folder that survives upgrades. See the Nova section.
🎯 Takeaway: Upgrade in small steps, back up before every step, and read the release notes before you touch anything.
Cleaning up
After the last step, I removed the old container images and the temporary copies I’d made of configuration files. That freed about 17 GB of disk space. The backups are still there in case I need to go back.
Conclusion
The private cloud now runs OpenStack 2026.2 on Ubuntu 24.04. All the virtual machines that run my Kubernetes clusters are up, the network and storage services are healthy, and Vaultwarden still answers.