Changes for doc/getting_started/upgrade_guide/2025Q4_2026Q2.md: 693 added lines, 0 removed lines.
Original line number
Diff line number
Diff line
# OpenSlice Upgrade Guide from 2025Q4 to 2026Q2
This guide upgrades a running OpenSlice instance from release 2025Q4 to release 2026Q2. Follow the
section that matches how the instance was installed: [Kubernetes](#upgrading-a-kubernetes-deployment) or [Docker Compose](#upgrading-a-docker-compose-deployment).
The two paths differ in where your configuration lives. Docker Compose keeps it in generated files
that sit beside templates the new release updates, so every upgrade asks you to merge. Helm keeps it
in a values file outside the chart, which the upgrade never touches.
### What changes in this release
The complete difference between the two tags, across both deployment methods, as perceived in the main project:
| File | Change |
| ---- | ------ |
| `compose/docker-compose.yaml.configure` | `SECRETS_CONTROLLER_ENABLE` added to the `osom` service |
| `compose/deploy.sh` | now clones `org.etsi.osl.mcp.backend` |
| `compose/docker-images-build.sh` | removed |
| `compose/readme_old.txt` | removed |
| `kubernetes/helm/openslice/Chart.yaml` | chart 3.0.0 to 4.1.0, appVersion 2026Q2 |
> **Note:** The expression matches whatever tag is currently present, so it works whether you are
> coming from `:latest` or from a previous pin. An expression anchored on `:latest` would work once
> and then silently match nothing on every later upgrade.
The build in the next step tags what it produces with these names, so afterwards `docker ps` reports
the release you are running, and the 2025Q4 images remain on disk for a rollback. Older images are also available online by tag, so there is no compulsory need to keep them locally.
### 5. Build the new release
`deploy.sh` moves every `org.etsi.osl.*` checkout to 2026Q2 and rebuilds the jars and the TMF portal
bundle. Run it from the folder that holds the checkouts, not from inside one of them.
docker compose --profile prod up -d mysql-portal &&sleep 60
docker exec-i amysql sh -c'mysql -u root -p"$MYSQL_ROOT_PASSWORD"'\
< ~/openslice-backup-YYYY-MM-DD.sql
docker compose --profile prod up -d# no --build: reuse the 2025Q4 images
docker compose --profile prod restart
docker compose restart nginx
```
The 2025Q4 images remain on disk under whatever tag that release's Compose file named, and restoring
the backup file points at them again, so `up -d` without `--build` reuses them. On a first upgrade
from a stock installation that tag is `:latest`.
> **Note:** The Web UI is the exception. `dist/` now holds the 2026Q2 bundle, so to roll the portal
> back as well, run `./deploy.sh 2025Q4` again from the folder holding the checkouts.
---
## Common local modifications
These are the settings that the 2025Q4 deployment guide asks you to configure, together with those
that deployments commonly add themselves. On Kubernetes they live in your values file and pass
through the upgrade untouched. The list matters for Docker Compose, where step 3 asks you to merge
the new release's three lines into a file that holds all of them.
Unless stated otherwise, these are found in `docker-compose.yaml`.
| Modification | Symptom if lost |
| ------------ | --------------- |
| MySQL `portaluser` and `keycloak` passwords, in `compose/mysql-init/01-databases.sql` and `DB_PASSWORD` | Keycloak cannot reach its database on any deployment built from a fresh volume |
| `KEYCLOAK_PASSWORD` for the administration console | reverts to the shipped default on a fresh Keycloak database |
| Keycloak issuer changed from `http://keycloak:8080` to your own URL | every authenticated request returns `401` |
| `KEYCLOAK_FRONTEND_URL` on the `keycloak` service | the issuer follows the request `Host` header again |
| `bugzillaurl`, `bugzillakey`, `main_operations_product` | the Bugzilla connector silently stops working |
| `SPRING_AI_OLLAMA_*` and the system prompt on `oslmcpbackend` | the assistant addresses the wrong LLM |
| A kubeconfig placed in `compose/kubedir/` (untracked, survives the checkout) | CRIDGE loses access to its cluster |
| A pinned third-party image updated, for example Portainer | the container restarts continuously |
| Services removed from the `prod` profile, and their `location` blocks in `nginx.conf` | they start again and fail against dependencies you never deployed, or nginx refuses to start |
| `server_name` in `nginx.conf` | no effect while it remains the only server block |
| Host and API URLs in `org.etsi.osl.portal.web/src/js/config.js` | the portal addresses `localhost` from the browser |
| `TITLE` and branding in `config.prod.json`, `theming.scss`, `config.theming.json` | your branding reverts to the shipped text |
| The release name hardcoded in `config.theming.json`, inside `FOOTER_HTML` | the footer continues to name the release you branded on, whatever `PORTALVERSION` reports |
| Edits to the tracked `compose/keycloak-init/realm-export.json` | the checkout aborts on any release that changes that file |
`deploy.sh` leaves all of these untouched, so the only item this upgrade requires you to correct by
hand is the version string in the two Web UI configuration files.
### The Keycloak issuer on Docker Compose
Keycloak constructs the `iss` claim of a token from the `Host` header of the request, so a token
obtained through nginx carries your host name while the shipped template expects
`http://keycloak:8080`. The two disagree. Signing in still succeeds, and then every authenticated
request returns `401`.
Two changes are required, and losing either one breaks authentication:
1. Replace `http://keycloak:8080` with your deployment URL in `docker-compose.yaml`.
2. Set `KEYCLOAK_FRONTEND_URL` on the `keycloak` service.
> **Important Note:** Do not rewrite `proxy_pass http://keycloak:8080/auth` in `nginx.conf`. That
> occurrence is the internal proxy target on the Docker network and must remain a container name.
> **Note:** The backends read the OpenID configuration at start-up, so they must be able to reach
> that URL. On a cloud virtual machine behind NAT the host frequently cannot reach its own public
> address. Whatever you configured for this at installation time is host-level configuration that
> the upgrade leaves alone, so confirm it is still in place.
On Kubernetes the chart handles all of this from `rooturl`.