3369 Commits
Author SHA1 Message Date
cozystack-ci[bot] c294e5fd64 Pin promoted packages artifact for v1.6.5
Signed-off-by: cozystack-ci[bot] <274107086+cozystack-ci[bot]@users.noreply.github.com>
2026-10-16 10:06:55 +00:00
cozystack-ci[bot] 0824833c4b Prepare release v1.6.5 (promoted from v1.6.5-rc.3)
Signed-off-by: cozystack-ci[bot] <274107086+cozystack-ci[bot]@users.noreply.github.com>
2026-10-16 10:06:52 +00:00
cozystack-ci[bot] 8ea06cdab5 Prepare release v1.6.5-rc.3
Signed-off-by: cozystack-ci[bot] <274107086+cozystack-ci[bot]@users.noreply.github.com>
2026-10-16 07:24:42 +00:00
myasnikovdaniil 5a7531a339 [Backport release-1.6] fix(tcp-balancer): rename backends and pin HAProxy so the chart starts on 3.3+ (#4516)
## What this PR does

Backports #4366 to release-1.6. All three original commits applied
without conflicts and retain their cherry-pick references.

HAProxy is pinned to 3.4.4 and backend names no longer collide with
frontend names. An empty whitelist leaves Kubernetes and Talos frontends
unfiltered. Enabling whitelistHTTP without a whitelist fails rendering.

Validation passed with 9 Helm tests, five rendered configurations
checked by HAProxy 3.4.4, and package generation without changes. The
old chart reproduces the name collision. Removing only the HTTP reject
rule makes the regression test fail.

### Downstream repositories

- [x] No downstream repository is affected by this change
- [ ] [cozystack/website](https://github.com/cozystack/website) -
follow-up:
- [ ]
[cozystack/terraform-provider-cozystack](https://github.com/cozystack/terraform-provider-cozystack)
- follow-up:
- [ ]
[cozystack/ansible-cozystack](https://github.com/cozystack/ansible-cozystack)
- follow-up:
- [ ] [cozystack/ccp](https://github.com/cozystack/ccp) - follow-up:
- [ ] [cozystack/talm](https://github.com/cozystack/talm) - follow-up:
- [ ] [cozystack/cozyhr](https://github.com/cozystack/cozyhr) -
follow-up:
- [ ] [cozystack/cozy-proxy](https://github.com/cozystack/cozy-proxy) -
follow-up:
- [ ]
[cozystack/cozystack-telemetry-server](https://github.com/cozystack/cozystack-telemetry-server)
- follow-up:
- [ ]
[cozystack/external-apps-example](https://github.com/cozystack/external-apps-example)
- follow-up:
- [ ] [cozystack/examples](https://github.com/cozystack/examples) -
follow-up:
- [ ] [cozystack/community](https://github.com/cozystack/community) -
follow-up:

### Release note

```release-note
fix(tcp-balancer): backport HAProxy 3.4.4, distinct backend names and whitelist validation to 1.6.
```
2026-10-16 11:46:44 +05:00
myasnikovdaniil 2b90e8cf45 [Backport release-1.6] fix(kubernetes): break bootstrap-token Job out of Helm hook to unblock fresh installs (#4541)
<!-- Thank you for making a contribution! Here are some tips for you:
- Use Conventional Commits for the PR title: `type(scope): description`
- Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore
- Scopes are not an exhaustive list — pick the most specific scope for
the change and extend the list when a genuinely new area appears.
Examples:
- System components: dashboard, platform, operator, cilium, kube-ovn,
linstor, fluxcd, cluster-api
- Managed apps: postgres, mariadb, redis, kafka, clickhouse,
virtual-machine, kubernetes
- Development and maintenance: api, hack, tests, ci, docs, maintenance
- Breaking changes: append `!` after type/scope (`feat(api)!: ...`) or
add a `BREAKING CHANGE:` footer
- If it's a work in progress, consider creating this PR as a draft.
- Don't hesistate to ask for opinion and review in the community chats,
even if it's still a draft.
- Add the label `backport` if it's a bugfix that needs to be backported
to a previous version.
-->

## What this PR does

Backports #3887 to `release-1.6`. The fix reached `main` only: `v1.6.3`
and `v1.6.4` both still ship the bootstrap-token Job as a
`post-install,post-upgrade` Helm hook, and `git tag --contains` on the
merge commit returns `v1.7.0-alpha.1` and nothing from the 1.6 line.
Tracked as #4539.

#3875 describes the deadlock this removes: the chart upgrade waits for
`MachineDeployment` and the child HelmReleases, workers cannot register
without the `bootstrap-token-<id>` Secret in the guest cluster, and the
hook that creates that Secret only runs once the wait has already
succeeded. The wait cannot succeed without nodes, so the upgrade times
out and Flux retries the same cycle indefinitely.

It is deterministic rather than flaky, and it takes out every tenant
Kubernetes cluster on the platform at once. What makes the backport
worth filing separately: anyone hitting this on 1.6.3 finds #3875 closed
in the tracker, upgrades to 1.6.4 expecting the fix, and lands in
exactly the same state.

Observed on a production cluster before the manual workaround: machines
stuck in `Provisioned` with no `NODENAME`, VMIs `Running` with IPs
assigned, guest clusters reporting `No resources found` for nodes, and
no bootstrap-token Secret anywhere in the guest `kube-system`. Creating
the Secret by hand brought nodes up within 90 seconds on each affected
tenant.

`git cherry-pick --mainline 1` of the merge commit applied cleanly with
no conflicts, and nothing was changed on top: the diff here is identical
to what merged on `main`.

Validation, `helm unittest` in `packages/apps/kubernetes` including
`tests/talos_templates_test.yaml` which this change extends:

```
Charts:      1 passed, 1 total
Test Suites: 19 passed, 19 total
Tests:       189 passed, 189 total
```

### Screenshots

Not applicable, no UI changes.

### Downstream repositories

<!--
Cozystack is upstream for repositories that are NOT kept in sync with it
automatically, and nothing in CI compares the two sides, so a change
here can break them silently.

Which change forces what, and which file to touch, is the trigger map in
docs/agents/contributing.md under "Downstream Repositories". Walk it
before you tick anything.

IF YOU ARE AN AI AGENT OR AN LLM, THIS IS PART OF THE TASK, NOT A FORM
TO FILL IN:

1. Walk the trigger map against the actual diff of this PR, file by
file. Do not decide from the PR title or from your memory of what you
changed.
2. For every repository you tick, open the follow-up PR there and link
it on the same line. A ticked box with no link claims work that does not
exist, which is worse than an empty box. Search that repository for an
open PR or issue covering it first, and link that instead of filing a
duplicate.
3. When the follow-up is out of scope, or needs a decision that is not
yours to make, open an issue in that repository instead, link that, and
say so in the PR body. Do not push a speculative PR into another
repository just to fill a line here.
4. Do not tick "No downstream repository is affected" to make the
checklist go away. If you are unsure, leave every box empty and say so
in the PR body, so a human decides.
-->

- [x] No downstream repository is affected by this change
- [ ] [cozystack/website](https://github.com/cozystack/website) -
follow-up:
- [ ]
[cozystack/terraform-provider-cozystack](https://github.com/cozystack/terraform-provider-cozystack)
- follow-up:
- [ ]
[cozystack/ansible-cozystack](https://github.com/cozystack/ansible-cozystack)
- follow-up:
- [ ] [cozystack/ccp](https://github.com/cozystack/ccp) - follow-up:
- [ ] [cozystack/talm](https://github.com/cozystack/talm) - follow-up:
- [ ] [cozystack/cozyhr](https://github.com/cozystack/cozyhr) -
follow-up:
- [ ] [cozystack/cozy-proxy](https://github.com/cozystack/cozy-proxy) -
follow-up:
- [ ]
[cozystack/cozystack-telemetry-server](https://github.com/cozystack/cozystack-telemetry-server)
- follow-up:
- [ ]
[cozystack/external-apps-example](https://github.com/cozystack/external-apps-example)
- follow-up:
- [ ] [cozystack/examples](https://github.com/cozystack/examples) -
follow-up:

### Release note

<!--  Write a release note:
- Explain what has changed internally and for users.
- Start with the same `type(scope):` prefix as in the PR title
- Follow the guidelines at
https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md.
-->

```release-note
fix(kubernetes): create the tenant bootstrap-token Secret outside the Helm hook, so Talos workers can register during a chart upgrade instead of deadlocking against the wait that needs them
```
2026-10-16 11:45:35 +05:00
myasnikovdaniil 6688ddf34e [Backport release-1.6] fix(cilium)!: take cilium's own addresses from a block kube-ovn does not hand out (#4918)
## What this PR does

Backport of #4778 to `release-1.6`, fixes #3740 on the 1.6 line.

On the kube-ovn variants (`isp-full`, `isp-full-generic`) cilium
allocates no pod IPs, but it still takes its router IP and the Gateway
API ingress IP from `Node.spec.podCIDR`, a /24 out of the same range
kube-ovn hands pods from, so sooner or later kube-ovn gives a pod an
address cilium already holds. With this change cilium runs `ipam.mode:
cluster-pool` with a /29 per node out of the last /21 of
`networking.podCIDR`, platform passes the same range to kube-ovn as
`--default-exclude-ips`, and a post-upgrade hook in the cilium chart
moves existing clusters. Mechanism and hook steps are the same as in
#4778, its description has the details.

This is breaking for a patch release, please read before merging:

- `networking.podCIDR` has to be /20 or wider on the kube-ovn variants,
otherwise platform refuses to render and the upgrade stops before
anything changes. Widening the value later doesn't help, the hook
refuses a block outside the subnet the cluster was installed with.
- A /21 of /29s caps these variants at 256 nodes.
- Every cilium agent restarts twice, once for the config change and once
in the hook. While the cilium release is failed, packages that depend on
networking wait for it.
- If kube-ovn already handed out an address from the last /21, the hook
names that address and stops before it moves any node. Recreate the pods
holding it and the next retry goes through.
- Rolling back to 1.6.4 brings `ipam.mode: kubernetes` back, agents take
their /24 again, and the exclusions stay in `ovn-default`.

### Differences from #4778

- No slim variants on release-1.6, so the `cozystack.platform.slim` gate
is gone and the pool is wired in the `isp-full` and `isp-full-generic`
branches only. `isp-hosted` renders `noop` and is not touched.
- The code around the wiring in `system.yaml` is release-1.6's (no
`gateway.http2`, no `networking.encryption`, the older
`cozystack.platform.package` call).
- The wiring test for `isp-slim` is left out of the cherry-pick, the
second commit adds one for `isp-hosted` with a /24 pod CIDR, which has
to keep rendering without the /20 requirement.
- `packages/system/cilium` has no `make test` target here, so
`hack/helm-unit-tests.sh` would skip the new suite without a word. The
third commit adds it.
- The follow-up from main that loads `test_helper` in
`hack/cilium-ipam-migration.bats` is not applied. release-1.6 has no
`hack/test_helper.bash` and runs `hack/*.bats` through
`hack/cozytest.sh`, with that line the file doesn't load.
- release-1.6 ships kube-ovn v1.15.10, #4778 was written against
v1.15.26.

### Validation

- `helm unittest`: cilium 11/11, platform 113/113 with #4808 merged.
`hack/cilium-ipam-migration.bats` passes 27/27 through
`hack/cozytest.sh`.
- Live hook run on a three-node Talos cluster with kube-ovn v1.15.10. I
put cilium on the release-1.6 chart first, then upgraded to this branch
with `helm upgrade` (operator stopped, HelmRelease suspended). A pod
pinned to `10.244.250.10` made the hook add the block and the old
ingress IPs to `excludeIps` of `ovn-default`, name that address and stop
before moving any node. After deleting the pod the same upgrade moved
all three nodes to /29s from `10.244.248.0/21`, router and ingress IPs
inside. The available range of the subnet ends at `10.244.247.255`, no
pod IP is duplicated, and pod to pod across nodes, DNS and a ping to a
VM pod IP work. A third run of the same upgrade restarted nothing and
left the CIDRs as they were.
- Rolling the release back on that cluster returned the agents to their
/24s with new ingress IPs, and `excludeIps` stayed until I patched it by
hand.
- Not run: the upgrade through the operator, the generic variant,
Gateway API traffic (no gateway on that cluster). kube-ovn still admits
a pod with a static `ovn.kubernetes.io/ip_address` inside the block
after the migration, the hook looks at it only while migrating.

### Downstream repositories

The website note for this change is cozystack/website#739, merged for
`docs/next`. The v1.6 docs need the same note, not opened yet, so the
box stays empty.

- [ ] No downstream repository is affected by this change
- [ ] [cozystack/website](https://github.com/cozystack/website) -
follow-up:
- [ ]
[cozystack/terraform-provider-cozystack](https://github.com/cozystack/terraform-provider-cozystack)
- follow-up:
- [ ]
[cozystack/ansible-cozystack](https://github.com/cozystack/ansible-cozystack)
- follow-up:
- [ ] [cozystack/ccp](https://github.com/cozystack/ccp) - follow-up:
- [ ] [cozystack/talm](https://github.com/cozystack/talm) - follow-up:
- [ ] [cozystack/cozyhr](https://github.com/cozystack/cozyhr) -
follow-up:
- [ ] [cozystack/cozy-proxy](https://github.com/cozystack/cozy-proxy) -
follow-up:
- [ ]
[cozystack/cozystack-telemetry-server](https://github.com/cozystack/cozystack-telemetry-server)
- follow-up:
- [ ]
[cozystack/external-apps-example](https://github.com/cozystack/external-apps-example)
- follow-up:
- [ ] [cozystack/examples](https://github.com/cozystack/examples) -
follow-up:

### Release note

```release-note
fix(cilium)!: on the kube-ovn variants cilium now takes its router and gateway api ingress ips from the last /21 of networking.podCIDR, which kube-ovn no longer hands out, so pods stop landing on addresses cilium holds. existing clusters move on upgrade through a post-upgrade hook, and each cilium agent restarts twice, once for the config change and once in the hook. networking.podCIDR needs /20 or wider on these variants, and a /21 of /29s caps them at 256 nodes.
```
2026-10-14 19:38:21 +05:00
myasnikovdaniil 858478cf70 [Backport release-1.6] fix(monitoring): send alerts to every Alertmanager replica (#4890)
## What this PR does

Backport of #4889 to `release-1.6`. The commit is cherry-picked from
9d4221b89. The only conflict was in `templates/_helpers.tpl`, which is
shorter on this branch, so the new `monitoring.alertmanager.replicas`
helper is appended to the release-1.6 file and nothing else from main
comes along.

The vmalert and VMAlertmanager templates here are the same as on main
before the fix, a single notifier on the shared Service and
`replicaCount: 3`, so the change applies as is. The monitoring chart
tests pass on this branch, 7 suites and 50 tests, the new suite
included.

### Screenshots

Not a UI change.

### Downstream repositories

- [x] No downstream repository is affected by this change
- [ ] [cozystack/website](https://github.com/cozystack/website) -
follow-up:
- [ ]
[cozystack/terraform-provider-cozystack](https://github.com/cozystack/terraform-provider-cozystack)
- follow-up:
- [ ]
[cozystack/ansible-cozystack](https://github.com/cozystack/ansible-cozystack)
- follow-up:
- [ ] [cozystack/ccp](https://github.com/cozystack/ccp) - follow-up:
- [ ] [cozystack/talm](https://github.com/cozystack/talm) - follow-up:
- [ ] [cozystack/cozyhr](https://github.com/cozystack/cozyhr) -
follow-up:
- [ ] [cozystack/cozy-proxy](https://github.com/cozystack/cozy-proxy) -
follow-up:
- [ ]
[cozystack/cozystack-telemetry-server](https://github.com/cozystack/cozystack-telemetry-server)
- follow-up:
- [ ]
[cozystack/external-apps-example](https://github.com/cozystack/external-apps-example)
- follow-up:
- [ ] [cozystack/examples](https://github.com/cozystack/examples) -
follow-up:
- [ ] [cozystack/community](https://github.com/cozystack/community) -
follow-up:

Same diff as #4889, two templates, the helpers and a test file of
`packages/system/monitoring`, so no trigger map entry applies.

### Release note

```release-note
fix(monitoring): vmalert now sends alerts to every Alertmanager replica instead of the shared Service, so the Alertmanager cluster deduplicates them and a long-running alert no longer produces repeated firing and resolved notifications.
```
2026-10-14 18:30:14 +05:00
Myasnikov Daniil c9c21bb2ea test(cilium): run the chart's helm unittest suites
hack/helm-unit-tests.sh picks the packages it tests by probing for a
make test target, and the cilium package had none, so make unit-tests
and CI would skip the IPAM pool suite this package now carries without
saying so.

Assisted-by: LLM
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
2026-10-14 16:29:34 +05:00
Myasnikov Daniil 8d12955795 test(platform): pin the cilium pool wiring to the variants release-1.6 has
The cherry-pick leaves out main's case for the slim variants, which
release-1.6 does not have, so that commit's suite stays green on its
own. isp-hosted is the one system variant here without kube-ovn, and
the /20 requirement must not reach it, so the case renders it with a
pod CIDR the kube-ovn variants refuse.

Assisted-by: LLM
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
2026-10-14 16:29:34 +05:00
Yan Bondarenko df320baa14 fix(cilium)!: take cilium's own addresses from a block kube-ovn does not hand out
On the kube-ovn variants Cilium allocates no pod addresses, but the agent
still takes its router IP and the Gateway API Ingress IP from its
allocation CIDR. In ipam.mode kubernetes that is Node.spec.podCIDR, which
the documented installs slice from the same range kube-ovn allocates pods
from, so kube-ovn sooner or later hands a pod an address Cilium already
holds.

Cilium now runs ipam.mode cluster-pool on the kube-ovn variants, with a
/29 per node from the last /21 of networking.podCIDR, and kube-ovn
excludes that /21 through --default-exclude-ips. The block stays inside
the pod CIDR on purpose. Envoy reaches Gateway API backends from the
node's Ingress IP, and kube-ovn masquerades host-originated traffic only
when the source lies in one of its subnets, so a block outside them such
as 100.65.0.0/16 breaks Gateway API traffic that crosses nodes.

A post-upgrade hook moves existing clusters. It first checks that the
block has a /29 for every node and lies inside kube-ovn's default
subnet, and stops without changing anything otherwise. It adds the block
and every node's current Ingress IP to excludeIps of that subnet,
because the agent keeps a former Ingress IP in its ipcache as
reserved:ingress. It then waits until kube-ovn stops offering the block
and stops if an address in it is still allocated. kube-ovn leaves
excluded addresses out of the subnet status, so that check reads its IP
objects. Then, one node at a time, it clears the inherited /24 from the
CiliumNode, waits for the operator to allocate from the block and
restarts the agent.

networking.podCIDR now needs a prefix of /20 or shorter on the kube-ovn
variants, and the render fails otherwise. A /21 cut into /29s also caps
these variants at 256 nodes.

Assisted-by: LLM
Signed-off-by: Yan Bondarenko <202671653+yankawai@users.noreply.github.com>
(cherry picked from commit dc362fa591)
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
2026-10-14 16:29:34 +05:00
myasnikovdaniil ec9e105822 [Backport release-1.6] fix(velero): bump velero-plugin-for-aws to v1.14.4 so backups work on R2 (#4854)
# Description
Backport of #4834 to `release-1.6`.
2026-10-14 16:27:49 +05:00
myasnikovdaniil 4334c4b23a [Backport release-1.6] feat(openbao): optional static-key auto-unseal and apiserver egress label (#4906)
# Description
Backport of #4766 to `release-1.6`.
2026-10-14 14:31:44 +05:00
myasnikovdaniil 11a0dd2aca [Backport release-1.6] fix(dashboard): allow editing free-form objects in application forms (#4905)
# Description
Backport of #4682 to `release-1.6`.
2026-10-14 14:28:30 +05:00
Yasar Rahman b653abd734 fix(velero): bump velero-plugin-for-aws to v1.14.4 so backups work on R2
velero-plugin-for-aws v1.14.1 sets x-amz-tagging on every PutObject,
empty when the BackupStorageLocation configures no tags. Cloudflare R2
answers that with 501 NotImplemented ("Header 'x-amz-tagging' with value
'' not implemented"), so Velero cannot write backup metadata and every
backup to an R2 location fails, the cozy-default location included when
the platform bucket is on R2.

The plugin sends the header only when tags are configured since v1.14.3
(velero-plugin-for-aws#309, a backport of #299). v1.14.4 is the current
patch release of the 1.14 line, which upstream lists as the one
compatible with Velero 1.18, and adds only CVE dependency bumps on top
of v1.14.3.

Signed-off-by: Yasar Rahman <yasar.rehman@gmail.com>
Assisted-by: LLM
(cherry picked from commit 83aaa65ed1)
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
2026-10-14 14:12:06 +05:00
myasnikovdaniil 13e202a53e [Backport release-1.6] feat(monitoring): add optional email receiver to alertmanager (#4614)
## What this PR does

Manual backport of #3800 to `release-1.6`.

The automated backport, #4609, stopped on a conflict in
`packages/system/monitoring-rd/cozyrds/monitoring.yaml` and pushed the
markers as its only commit, so it would ship conflict markers in the
ApplicationDefinition if merged.

That file is generated, and its schema and `keysOrder` lines already
differ between main and 1.6 for reasons unrelated to this change.
Everything else applies unchanged. I kept the `release-1.6` version of
the file and ran `make generate` in `packages/extra/monitoring` with
cozyvalues-gen 1.6.0. The README and `values.schema.json` came out
identical to the cherry-picked ones, and the regenerated schema adds
exactly the eight `alerta.alerts.email` properties that #3800 adds on
main, with nothing removed.

Verified on this branch: `helm unittest` passes 164 tests in 8 suites
for `packages/system/monitoring`, both new email suites included, and 9
tests for `packages/extra/monitoring`. The file set and line counts
match #3800.

Close #4609 in favour of this one, or tell me to take a different route
and I will.

### Screenshots

Not a UI change.

### Downstream repositories

Same walk as #3800: `packages/extra/monitoring` gains values fields, its
reference page on the website regenerates from `README.md` on the next
stable tag, and the Terraform provider does not model the monitoring
service. No package is added or renamed, and no CRD, tooling or node
contract is touched.

- [x] No downstream repository is affected by this change
- [ ] [cozystack/website](https://github.com/cozystack/website) -
follow-up:
- [ ]
[cozystack/terraform-provider-cozystack](https://github.com/cozystack/terraform-provider-cozystack)
- follow-up:
- [ ]
[cozystack/ansible-cozystack](https://github.com/cozystack/ansible-cozystack)
- follow-up:
- [ ] [cozystack/ccp](https://github.com/cozystack/ccp) - follow-up:
- [ ] [cozystack/talm](https://github.com/cozystack/talm) - follow-up:
- [ ] [cozystack/cozyhr](https://github.com/cozystack/cozyhr) -
follow-up:
- [ ] [cozystack/cozy-proxy](https://github.com/cozystack/cozy-proxy) -
follow-up:
- [ ]
[cozystack/cozystack-telemetry-server](https://github.com/cozystack/cozystack-telemetry-server)
- follow-up:
- [ ]
[cozystack/external-apps-example](https://github.com/cozystack/external-apps-example)
- follow-up:
- [ ] [cozystack/examples](https://github.com/cozystack/examples) -
follow-up:
- [ ] [cozystack/community](https://github.com/cozystack/community) -
follow-up:

### Release note

```release-note
feat(monitoring): add optional email alerting through alerta.alerts.email, with configurable severity and alert-name selection and an SMTP password read from the fixed Secret alertmanager-email-password
```
2026-10-14 12:35:45 +05:00
myasnikovdaniil b50fdf532c [Backport release-1.6] fix(dashboard, foundationdb): show the connection ConfigMap to tenants (#4684)
## What this PR does

Backport of #4612 to `release-1.6`, together with its follow-up #4789.
All three commits are cherry-picked. Two of them needed their
`ApplicationDetailPage.test.tsx` cases added by hand, because on this
branch that file has none of the virtual machine tab tests they sit next
to on main.

FoundationDB keeps its connection string in a ConfigMap that tenants may
read, and the console had no view for ConfigMaps. The application page
gets a ConfigMaps tab for the ConfigMaps named in the application's
resource map, with a copy button for each value. Each read uses an
exact-name field selector, so no general ConfigMap access is needed. The
FoundationDB chart now renders its resource map with monitoring disabled
too, and tenant roles may read it. If the resource map stops being
readable after a successful read, the tab goes away instead of keeping
the old names.

### Validation

- All 6 FoundationDB chart tests pass, and so do all 338 console tests
in 52 files and the TypeScript check.
- Tests cover finding the ConfigMaps through the resource map, reading
only the named ones in the active namespace, copying a value, a failed
copy, a denied read, malformed resource maps, and a resource map that
answers 403 or 404 after a successful read. The four tests for the last
case fail without the #4789 commit.

### Screenshots

The tab is the same as in #4612, which has a screenshot of it.

### Downstream repositories

Walked the trigger map against the diff. It changes a FoundationDB chart
template and its test, and the console, with no values, schema, CRD or
`hack/` file, and the console is vendored in this repository. No
companion repository needs an update.

- [x] No downstream repository is affected by this change
- [ ] [cozystack/website](https://github.com/cozystack/website) -
follow-up:
- [ ]
[cozystack/terraform-provider-cozystack](https://github.com/cozystack/terraform-provider-cozystack)
- follow-up:
- [ ]
[cozystack/ansible-cozystack](https://github.com/cozystack/ansible-cozystack)
- follow-up:
- [ ] [cozystack/ccp](https://github.com/cozystack/ccp) - follow-up:
- [ ] [cozystack/talm](https://github.com/cozystack/talm) - follow-up:
- [ ] [cozystack/cozyhr](https://github.com/cozystack/cozyhr) -
follow-up:
- [ ] [cozystack/cozy-proxy](https://github.com/cozystack/cozy-proxy) -
follow-up:
- [ ]
[cozystack/cozystack-telemetry-server](https://github.com/cozystack/cozystack-telemetry-server)
- follow-up:
- [ ]
[cozystack/external-apps-example](https://github.com/cozystack/external-apps-example)
- follow-up:
- [ ] [cozystack/examples](https://github.com/cozystack/examples) -
follow-up:
- [ ] [cozystack/community](https://github.com/cozystack/community) -
follow-up:

### Release note

```release-note
fix(dashboard): backport FoundationDB connection ConfigMaps to release-1.6
```
2026-10-14 12:35:35 +05:00
myasnikovdaniil 2388d09965 [Backport release-1.6] fix(etcd): leave compaction to etcd and pass the real quota to defrag (#4874)
## What this PR does

backport of #4873 to `release-1.6`. the commit is cherry-picked
unchanged from fe59a6bf9.

the defrag CronJob and the EtcdCluster template are the same on this
branch: etcd compacts itself with `autoCompactionMode: periodic` and a
5m retention, and `quotaBackendBytes` comes from the same
`calculateQuotaBackendBytes` helper. so the job runs a second compaction
that fails with `mvcc: required revision has been compacted` on idle
clusters, and it measures `dbQuotaUsage` against the tool's 2 GiB
default. it now passes `--compaction=false` and the chart's own quota.
the etcd chart tests pass here, 21 of 21.

### Screenshots

Not a UI change.

### Downstream repositories

- [x] No downstream repository is affected by this change
- [ ] [cozystack/website](https://github.com/cozystack/website) -
follow-up:
- [ ]
[cozystack/terraform-provider-cozystack](https://github.com/cozystack/terraform-provider-cozystack)
- follow-up:
- [ ]
[cozystack/ansible-cozystack](https://github.com/cozystack/ansible-cozystack)
- follow-up:
- [ ] [cozystack/ccp](https://github.com/cozystack/ccp) - follow-up:
- [ ] [cozystack/talm](https://github.com/cozystack/talm) - follow-up:
- [ ] [cozystack/cozyhr](https://github.com/cozystack/cozyhr) -
follow-up:
- [ ] [cozystack/cozy-proxy](https://github.com/cozystack/cozy-proxy) -
follow-up:
- [ ]
[cozystack/cozystack-telemetry-server](https://github.com/cozystack/cozystack-telemetry-server)
- follow-up:
- [ ]
[cozystack/external-apps-example](https://github.com/cozystack/external-apps-example)
- follow-up:
- [ ] [cozystack/examples](https://github.com/cozystack/examples) -
follow-up:
- [ ] [cozystack/community](https://github.com/cozystack/community) -
follow-up:

### Release note

```release-note
fix(etcd): the defrag job no longer compacts on top of etcd's periodic auto-compaction, and it evaluates its 80% quota threshold against the cluster's real quotaBackendBytes instead of 2 GiB.
```
2026-10-14 12:35:25 +05:00
myasnikovdaniil fdaa9e1572 [Backport release-1.6] fix(mongodb): set the s3 bucket and prefix on the bootstrap restore (#4780)
## What this PR does

backport of #4779 to `release-1.6`. the template change is cherry-picked
unchanged from a6cf0e5ce. one test needed an edit for this branch, see
below.

the bug is the same here, and v1.6.4 ships this exact template. with
`bootstrap.enabled: true` the chart renders a
`PerconaServerMongoDBRestore` without `spec.backupSource.s3.bucket`,
which the operator crd requires, so the api server rejects it and the
release fails. the restore now takes the bucket and prefix from the same
helpers as the backup storage, so it reads from where the backups are
written. both places quote the values, the backup storage still leaves
out an empty prefix. a `destinationPath` that names no bucket fails at
render time.

this branch has no `backup.insecureSkipTLSVerify`. the backup storage
and the restore both hardcode `false`, so
`tests/restore-storage_test.yaml` checks `false` on both sides here
instead of setting the value to `true`.

- `helm unittest` passes 109 of 109 tests in 8 suites. before this
change it was 101 in 7.
- against the release-1.6 templates 7 of the 8 new cases fail, the same
7 as on main.
- `helm template` of the `PerconaServerMongoDB` gives the same picture
as on main for 8 `destinationPath` forms. 5 render the same storage, the
two bucket root forms only stop rendering a `prefix: null` the api
server prunes anyway, and `s3://2024/10` goes from ints the crd rejects
to strings.
- offline validation against the crd on this branch matches main. all 8
forms fail with `spec.backupSource.s3.bucket: Required value` before the
fix, and after it 7 pass and `s3://` stops at render time.
- `make generate` with cozyvalues-gen v1.6.0, the version this branch's
ci pins, leaves every generated file unchanged.
- `packages/apps/mongodb/Makefile` has no `test` target on this branch,
so ci does not run these suites here. i ran them by hand with
helm-unittest 1.1.2.
- no restore was run against a live cluster.

on upgrade, releases with `bootstrap.enabled: false` render the same
manifests as before. a release that still has `bootstrap.enabled: true`
creates its restore on the first reconcile after the upgrade, and the
operator starts restoring into the cluster as it is at that moment. the
release note says so.

### Screenshots

not a ui change.

### Downstream repositories

same diff as #4779, where the trigger map was walked file by file. no
entry matches.

- [x] No downstream repository is affected by this change
- [ ] [cozystack/website](https://github.com/cozystack/website) -
follow-up:
- [ ]
[cozystack/terraform-provider-cozystack](https://github.com/cozystack/terraform-provider-cozystack)
- follow-up:
- [ ]
[cozystack/ansible-cozystack](https://github.com/cozystack/ansible-cozystack)
- follow-up:
- [ ] [cozystack/ccp](https://github.com/cozystack/ccp) - follow-up:
- [ ] [cozystack/talm](https://github.com/cozystack/talm) - follow-up:
- [ ] [cozystack/cozyhr](https://github.com/cozystack/cozyhr) -
follow-up:
- [ ] [cozystack/cozy-proxy](https://github.com/cozystack/cozy-proxy) -
follow-up:
- [ ]
[cozystack/cozystack-telemetry-server](https://github.com/cozystack/cozystack-telemetry-server)
- follow-up:
- [ ]
[cozystack/external-apps-example](https://github.com/cozystack/external-apps-example)
- follow-up:
- [ ] [cozystack/examples](https://github.com/cozystack/examples) -
follow-up:
- [ ] [cozystack/community](https://github.com/cozystack/community) -
follow-up:

### Release note

```release-note
fix(mongodb): backport the bootstrap restore fix to 1.6. a mongodb app created with bootstrap.enabled now gets a PerconaServerMongoDBRestore with the s3 bucket and prefix of backup.destinationPath, so the api server accepts it and the operator looks for the backup where the backup storage wrote it.

on upgrade, an app that still has bootstrap.enabled set to true, for example after an earlier restore attempt that failed on the missing bucket, creates its restore on the first reconcile, and the operator restores the backup into the cluster as it is at that moment. set bootstrap.enabled to false before the upgrade on every mongodb app that should not be restored.
```
2026-10-14 12:35:15 +05:00
myasnikovdaniil 48bcb33ca5 [Backport release-1.6] fix(linstor): use severity warning in piraeus-datastore alerts (#4740)
## What this PR does

Backport of the LINSTOR severity fix and its alert-rule guard from #3799
to `release-1.6`, together with the guard's follow-up #4812. Seven
piraeus-datastore rules use `warn`, which the default Alerta alarm model
does not accept, and they now use `warning`. Alert names, expressions
and thresholds stay unchanged.

Cherry-picked `3ade16a380c9d03b83ff28ea02af3b800fdd1b0f` and
`bd2cc0a749531433a237a9c8a6e21a6f21dee200` with their authors and
cherry-pick references. The KEDA severity commit from the same main PR
is left out because the KEDA rule it fixes does not exist on
release-1.6. The follow-up from #4812 is cherry-picked too. It makes the
guard catch a quoted kind or a kind followed by a comment, and fail on a
rule group it cannot see into once template actions are stripped.

### Validation

- All nine checks in `hack/alert-severity-contract.bats` pass with
`hack/cozytest.sh` on this branch. The wider discovery finds the same 39
rule files as before and no rule group comes out empty.
- Against `release-1.6` at `da98ddc08` without the fix, the same
contract fails on exactly the seven `warn` rules corrected here.
- Delivery through Alertmanager and Alerta was not exercised.

### Screenshots

Not a UI change.

### Downstream repositories

The file-level trigger map was checked against both changed files: a
rule file under `packages/system/piraeus-operator/alerts/` and a new
test under `hack/`. No existing tool, make target, API schema, package,
output resource or documented workflow is renamed or changed. No
companion repository update is required.

- [x] No downstream repository is affected by this change
- [ ] [cozystack/website](https://github.com/cozystack/website) -
follow-up:
- [ ]
[cozystack/terraform-provider-cozystack](https://github.com/cozystack/terraform-provider-cozystack)
- follow-up:
- [ ]
[cozystack/ansible-cozystack](https://github.com/cozystack/ansible-cozystack)
- follow-up:
- [ ] [cozystack/ccp](https://github.com/cozystack/ccp) - follow-up:
- [ ] [cozystack/talm](https://github.com/cozystack/talm) - follow-up:
- [ ] [cozystack/cozyhr](https://github.com/cozystack/cozyhr) -
follow-up:
- [ ] [cozystack/cozy-proxy](https://github.com/cozystack/cozy-proxy) -
follow-up:
- [ ]
[cozystack/cozystack-telemetry-server](https://github.com/cozystack/cozystack-telemetry-server)
- follow-up:
- [ ]
[cozystack/external-apps-example](https://github.com/cozystack/external-apps-example)
- follow-up:
- [ ] [cozystack/examples](https://github.com/cozystack/examples) -
follow-up:
- [ ] [cozystack/community](https://github.com/cozystack/community) -
follow-up:

### Release note

```release-note
fix(linstor): backport accepted warning severity for seven piraeus-datastore alerts to release-1.6, with a regression guard for first-party alert rules
```
2026-10-14 12:35:04 +05:00
myasnikovdaniil 629dcc455d [Backport release-1.6] fix(platform): keep the legacy etcd-operator stopped after etcd adoption (#4739)
## What this PR does

Backport of #4738 to `release-1.6`, cherry-picked without changes from
`6248d458ad57c5991700dc26c5abc1340b1a05f4`.

Migration 50 scaled the legacy etcd-operator back to 1 after adopting
the legacy etcd clusters. Until a tenant's etcd HelmRelease reconciled
the new chart, Flux re-created the legacy EtcdCluster from the old one,
and the running legacy operator re-created the legacy StatefulSet and
took the legacy `etcd-headless` Service away from the adopted
EtcdMembers. The garbage collector deleted the Service when the new
chart pruned that EtcdCluster, and the adopted members'
`etcd-<i>.etcd-headless` names stopped resolving. This hit every tenant
etcd on a cluster upgraded from 1.4.3 to 1.6.4, and upgrades from 1.4
and 1.5 to 1.6 go through this branch. The operator now stays at 0 after
a successful adoption until the etcd-operator HelmRelease replaces it,
and a failed adoption still restores it through the EXIT trap. The full
timeline from the audit log and the repair for already upgraded clusters
are in #4738.

### Validation

- The commit applies cleanly to `release-1.6` at `da98ddc08`.
- `hack/cozytest.sh hack/migration-50-etcd-adopt.bats` passes all 29
tests on this branch. The new test fails against the release-1.6 script
with `FAIL: the legacy operator was scaled back up after a successful
adoption`.

### Screenshots

Not a UI change.

### Downstream repositories

Same diff as #4738, where the trigger map was walked file by file. No
entry matches.

- [x] No downstream repository is affected by this change
- [ ] [cozystack/website](https://github.com/cozystack/website) -
follow-up:
- [ ]
[cozystack/terraform-provider-cozystack](https://github.com/cozystack/terraform-provider-cozystack)
- follow-up:
- [ ]
[cozystack/ansible-cozystack](https://github.com/cozystack/ansible-cozystack)
- follow-up:
- [ ] [cozystack/ccp](https://github.com/cozystack/ccp) - follow-up:
- [ ] [cozystack/talm](https://github.com/cozystack/talm) - follow-up:
- [ ] [cozystack/cozyhr](https://github.com/cozystack/cozyhr) -
follow-up:
- [ ] [cozystack/cozy-proxy](https://github.com/cozystack/cozy-proxy) -
follow-up:
- [ ]
[cozystack/cozystack-telemetry-server](https://github.com/cozystack/cozystack-telemetry-server)
- follow-up:
- [ ]
[cozystack/external-apps-example](https://github.com/cozystack/external-apps-example)
- follow-up:
- [ ] [cozystack/examples](https://github.com/cozystack/examples) -
follow-up:
- [ ] [cozystack/community](https://github.com/cozystack/community) -
follow-up:

### Release note

```release-note
fix(platform): backport to 1.6 the fix that keeps the legacy etcd-operator stopped after migration 50 adopts the legacy etcd clusters, so the adopted members keep their etcd-headless DNS names through the upgrade.
```
2026-10-14 12:34:55 +05:00
myasnikovdaniil 17f3386453 [Backport release-1.6] fix(postgres): cap the default shared_buffers at a quarter of the memory limit (#4725)
## What this PR does

Backport of #4724 to `release-1.6`, including the memory-request cap
required by CloudNativePG when memory is overcommitted.

The chart renders no `shared_buffers`, and CloudNativePG 1.28.2, the
operator version on this branch, does not set one either, so PostgreSQL
starts with its built-in 128MB. That is the whole memory limit on
`t1.nano` and half of it on `t1.micro`, the chart's default preset, and
a dump, index scans over a large table or a replica catching up after a
failover can fill the pool and get the instance OOMKilled. Below a 512Mi
memory limit the chart defaults `shared_buffers` to a quarter of the
limit with a 16MB floor, capped at the rendered memory request rounded
down to whole MiB. From 512Mi up nothing is rendered and those clusters
are unchanged. An explicit `shared_buffers` in `postgresql.parameters`
still wins.

On upgrade every cluster below 512Mi that does not set `shared_buffers`
gets the new value. With the CloudNativePG defaults the chart keeps,
`unsupervised` and `restart`, the operator restarts the replicas first
and then the primary in place, so writes pause for one PostgreSQL
restart, and a single-instance cluster is unavailable for that time.

### Validation

- The commit applies cleanly to `release-1.6` at `da98ddc08`.
- `helm unittest` passes all 50 tests in 7 suites on this branch. The
added cases cover memory overcommit, fractional MiB requests, a request
below the 16MB floor, explicit values and the unchanged 512Mi threshold.
Four cases fail against the previous PR template.
- `helm template` of the chart on this branch renders `t1.small` exactly
as before, and the default preset differs only by `shared_buffers:
"64MB"`.
- `make generate` with cozyvalues-gen v1.6.0, the version this branch's
CI pins, leaves the generated files unchanged.

### Screenshots

Not a UI change.

### Downstream repositories

Same diff as #4724, where the trigger map was walked file by file. No
entry matches.

- [x] No downstream repository is affected by this change
- [ ] [cozystack/website](https://github.com/cozystack/website) -
follow-up:
- [ ]
[cozystack/terraform-provider-cozystack](https://github.com/cozystack/terraform-provider-cozystack)
- follow-up:
- [ ]
[cozystack/ansible-cozystack](https://github.com/cozystack/ansible-cozystack)
- follow-up:
- [ ] [cozystack/ccp](https://github.com/cozystack/ccp) - follow-up:
- [ ] [cozystack/talm](https://github.com/cozystack/talm) - follow-up:
- [ ] [cozystack/cozyhr](https://github.com/cozystack/cozyhr) -
follow-up:
- [ ] [cozystack/cozy-proxy](https://github.com/cozystack/cozy-proxy) -
follow-up:
- [ ]
[cozystack/cozystack-telemetry-server](https://github.com/cozystack/cozystack-telemetry-server)
- follow-up:
- [ ]
[cozystack/external-apps-example](https://github.com/cozystack/external-apps-example)
- follow-up:
- [ ] [cozystack/examples](https://github.com/cozystack/examples) -
follow-up:
- [ ] [cozystack/community](https://github.com/cozystack/community) -
follow-up:

### Release note

```release-note
fix(postgres): backport the small-preset shared_buffers default to 1.6. Without an explicit shared_buffers and below a 512Mi memory limit, PostgreSQL now gets a quarter of the limit with a 16MB floor, capped at the memory request, instead of its built-in 128MB, so a full buffer pool no longer takes the whole limit on t1.nano or half of it on t1.micro. Affected clusters restart their instances once on upgrade, the primary last.
```
2026-10-14 12:34:45 +05:00
myasnikovdaniil 29642c105b [Backport release-1.6] fix(nats): enable JetStream for the generated account (#4677)
## What this PR does

Backport of #4675 to `release-1.6`, cherry-picked without changes from
`15b7092f3ada7c26fbaa7c67be26e59ced73992f`. #4675 is merged in main now.

With `users` configured and `jetstream.enabled: true`, the application
chart enables JetStream on the server but generates account `A` without
it. Authentication and ordinary NATS messaging work, while
`$JS.API.INFO` returns error 10039, "JetStream not enabled for account".

The generated account now gets `jetstream: true` when persistent
messaging is enabled and the account does not set JetStream itself.
Tenant-supplied limits, explicit disablement, other accounts and the
existing generated-user merge are kept. nats-server matches config keys
case-insensitively and walks the account map in no fixed order, so a
`JetStream` key in any casing counts as set. Otherwise the account would
carry both keys and the server would apply either one, changing from
restart to restart.

Existing instances with `users` pick this up on upgrade. The rendered
NATS config changes, so the StatefulSet rolls its pods once, and account
`A` gets JetStream without account limits unless
`config.merge.accounts.A.jetstream` sets them.

### Validation

- The commit applies cleanly to `release-1.6` at `da98ddc08`.
- `helm unittest` passes all 65 application-chart tests on this branch.
- The run on NATS Server 2.11.10 is described in #4675.

### Screenshots

Not a UI change.

### Downstream repositories

The diff changes an application template and chart tests only. Public
values, schemas, output resource names and tooling contracts are
unchanged. The website NATS documentation contains no account-level
workaround to remove. No downstream trigger applies.


- [x] No downstream repository is affected by this change
- [ ] [cozystack/website](https://github.com/cozystack/website) -
follow-up:
- [ ]
[cozystack/terraform-provider-cozystack](https://github.com/cozystack/terraform-provider-cozystack)
- follow-up:
- [ ]
[cozystack/ansible-cozystack](https://github.com/cozystack/ansible-cozystack)
- follow-up:
- [ ] [cozystack/ccp](https://github.com/cozystack/ccp) - follow-up:
- [ ] [cozystack/talm](https://github.com/cozystack/talm) - follow-up:
- [ ] [cozystack/cozyhr](https://github.com/cozystack/cozyhr) -
follow-up:
- [ ] [cozystack/cozy-proxy](https://github.com/cozystack/cozy-proxy) -
follow-up:
- [ ]
[cozystack/cozystack-telemetry-server](https://github.com/cozystack/cozystack-telemetry-server)
- follow-up:
- [ ]
[cozystack/external-apps-example](https://github.com/cozystack/external-apps-example)
- follow-up:
- [ ] [cozystack/examples](https://github.com/cozystack/examples) -
follow-up:
- [ ] [cozystack/community](https://github.com/cozystack/community) -
follow-up:

### Release note



```release-note
fix(nats): enable JetStream on the account generated for users when jetstream.enabled is true, keeping any explicit account-level JetStream setting. Instances with users roll their NATS pods once on upgrade.
```
2026-10-14 12:34:36 +05:00
myasnikovdaniil 6086bd1b46 [Backport release-1.6] feat(keycloak): expose zone placement for Keycloak and the database proxy (#4856)
# Description
Backport of #4606 to `release-1.6`.
2026-10-14 12:33:56 +05:00
myasnikovdaniil f95ba62000 [Backport release-1.6] fix(cert-manager): enable the Gateway API solver in the host cert-manager (#4808)
# Description
Backport of #4039 to `release-1.6`.
2026-10-14 12:33:46 +05:00
myasnikovdaniil 008c0256b4 [Backport release-1.6] fix(cozy-lib): round the sanitized CPU request up to a whole milli-CPU (#4590)
# Description
Backport of #3522 to `release-1.6`.
2026-10-14 12:33:36 +05:00
myasnikovdaniil e23815ba00 [Backport release-1.6] fix(kubernetes): apply worker TalosConfigTemplate server-side (#4575)
# Description
Backport of #4163 to `release-1.6`.
2026-10-14 12:33:27 +05:00
myasnikovdaniil 0c5564aae4 [Backport release-1.6] fix(kubernetes): probe Keycloak CRDs by output in oidc-bootstrap cleanup (#4571)
# Description
Backport of #3520 to `release-1.6`.
2026-10-14 12:33:17 +05:00
Yan Bondarenko 6af3583dd8 docs(openbao): document the static seal trade-off and the Shamir migration
With the static seal the key sits in a Secret in the same cluster as the
data it unwraps, so the barrier is only as strong as access to Secrets
in that namespace, to etcd and to backups. The README now says so before
the reader picks a seal, and it says what the key identifier is for,
since OpenBAO picks the key for stored data by it.

Tenant roles grant nothing on Secrets and no pods/log, so a cluster
administrator creates the key Secret and reads the log line that
confirms a re-wrap.

The StatefulSet uses the OnDelete strategy, so neither a seal migration
nor the apiserver egress label reaches a running pod until it is
replaced. The README describes the migration from Shamir step by step,
following the OpenBAO seal migration guide, and says that pods created
before the label have to be replaced once.

The migration starts with a backup. The standalone file backend is not
transactional, so its volume is copied with the server stopped or
snapshotted atomically. The upgrade that sets allowMigration is the
point of no return for the chart, and the README says how a cluster
administrator backs out of it before any pod is replaced.

Assisted-by: LLM
Signed-off-by: Yan Bondarenko <202671653+yankawai@users.noreply.github.com>
(cherry picked from commit 3ea7a95108)
2026-10-13 14:55:16 +00:00
Yan Bondarenko 80c64869e9 fix(openbao): constrain the seal values that reach the server config
The upstream chart passes the server config through tpl, and its start
script replaces upper case placeholders such as HOSTNAME anywhere in the
copied file. A key identifier with template delimiters would run as a
template inside helm-controller, which runs as cluster-admin, and an
upper case one could come out different on every pod. Both key
identifiers now take lowercase alphanumerics, hyphens, dots and
underscores.

The Secret names become pod volume names of the form userconfig-<name>,
which Kubernetes validates as DNS labels. Both name fields now take a
DNS label of at most 52 characters, and the volume entries are quoted.
The apps API only defaults against the generated schema, so Helm
enforces these patterns when it installs or upgrades the release.

A previous Secret equal to the current one mounts the same volume twice,
which the API server rejects for the StatefulSet, and OpenBAO refuses to
start when equal key identifiers name different key material. Both
cases now fail at render. The deepcopy functions for the Seal type are
regenerated as well.

Assisted-by: LLM
Signed-off-by: Yan Bondarenko <202671653+yankawai@users.noreply.github.com>
(cherry picked from commit bfbb5ac75f)
2026-10-13 14:55:16 +00:00
txmazing cf4b65ada3 feat(openbao): optional static-key auto-unseal and apiserver egress label
The OpenBAO app has no auto-unseal (#2787). Every restart of a server,
after a node drain, an image bump or an OOM kill, leaves it sealed until
an operator enters the Shamir key shares into each replica. In HA mode
the pods also hang at start (#2793). Cozystack's allow-to-apiserver
policy only admits egress from pods labelled
policy.cozystack.io/allow-to-apiserver, the app never set that label,
and service_registration "kubernetes" cannot reach the API server
without it.

A new seal value selects shamir, which stays the default, or OpenBAO's
seal "static". With static the chart renders the static seal stanza into
the standalone and the Raft config and mounts the key Secret named in
seal.secretName through the upstream chart's server.extraVolumes. The
chart never generates, stores or rotates the key, because a missed
lookup would replace it and leave the data unreadable.
seal.previousSecretName and seal.previousKeyId carry the n-1 key that
the static seal accepts during a rotation. The server pods always carry
the apiserver egress label.

Changing the seal of an initialized instance is a seal migration that
OpenBAO performs under bao operator unseal -migrate. The chart reads the
seal in use from the config ConfigMap the previous release rendered and
refuses a different seal.type unless seal.allowMigration acknowledges
the migration. Moving away from static needs the old stanza kept with
disabled = "true", which the chart does not render, so that direction is
refused regardless. The README documents the key Secret, the rotation
with the pod replacement that the OnDelete update strategy requires, and
the log line that confirms the re-wrap.

Signed-off-by: txmazing <txmazing@gmail.com>
Assisted-by: LLM
Signed-off-by: Yan Bondarenko <202671653+yankawai@users.noreply.github.com>
(cherry picked from commit 0c52dedbe2)
2026-10-13 14:55:16 +00:00
Yan Bondarenko 4ee828e421 fix(dashboard): mark a free-form field invalid when the schema rejects it
A JSON object that parses but fails the schema, for example on
minProperties, left the textarea with aria-invalid false, and nothing
linked it to the error list RJSF renders under the field, so assistive
technology announced the field as valid. The field now reports the
schema errors RJSF passes in and points aria-describedby at their list,
unless hideError keeps that list from rendering. The red help text
stays tied to input that is not a JSON object.

Assisted-by: LLM
Signed-off-by: Yan Bondarenko <202671653+yankawai@users.noreply.github.com>
(cherry picked from commit 96b35893a5)
2026-10-13 14:55:05 +00:00
Yan Bondarenko 62e1811219 fix(dashboard): allow editing free-form objects in application forms
Signed-off-by: Yan Bondarenko <202671653+yankawai@users.noreply.github.com>
Assisted-by: LLM
(cherry picked from commit d639113caf)
2026-10-13 14:55:05 +00:00
Yan Bondarenko 38bd21f3a8 fix(monitoring): send alerts to every Alertmanager replica
vmalert had a single notifier, the headless vmalertmanager-alertmanager
Service. It resolves to all three pods, but each alert reached one replica
at a time and moved to another when vmalert reconnected. On clusters running
1.6.4 all active alerts sat on one replica while the other two had none, and
on one of them the alert count of each replica changed about 170 times a
day. The Alertmanager cluster deduplicates notifications only when every
replica receives every alert. The replica an alert left let it expire and
sent a resolved notification, and the replica it reached sent a new firing
one.

vmalert now lists each Alertmanager pod as its own notifier, using the
<name>-<i>.<service>.<namespace>.svc address the operator itself gives
StatefulSet pods. The replica count comes from one helper that also sets
spec.replicaCount of the VMAlertmanager, so the two cannot drift.

Assisted-by: LLM
Signed-off-by: Yan Bondarenko <202671653+yankawai@users.noreply.github.com>
(cherry picked from commit 9d4221b890)
2026-10-12 19:46:32 +03:00
Yan Bondarenko 1241cfd4e5 fix(etcd): leave compaction to etcd and pass the real quota to defrag
The hourly defrag CronJob runs etcd-defrag with its defaults, which compact
to the latest revision before defragmenting. Every cluster already compacts
itself with a periodic five-minute retention, so the second compaction
either fails with "required revision has been compacted" when nothing was
written since, or drops the history that retention keeps for watchers to
resume from.

The same defaults evaluate dbQuotaUsage in the defrag rule against 2 GiB
rather than the quotaBackendBytes the cluster runs with, so the 80 percent
threshold fires at a different database size than intended.

Assisted-by: LLM
Signed-off-by: Yan Bondarenko <202671653+yankawai@users.noreply.github.com>
(cherry picked from commit fe59a6bf91)
2026-10-11 20:25:46 +03:00
Andrei Kvapil 4c8c53610a feat(keycloak): expose zone placement for the keycloak-db instances
The Keycloak StatefulSet and the database proxy can already be spread
across failure domains, but the CloudNativePG Cluster behind them could
only follow the cluster-wide topology constraint, with no way to pick
zones for this database alone. With both instances in one zone, losing
that zone loses the database and every login with it.

Add database.affinity (CloudNativePG shape) and
database.topologySpreadConstraints, with empty defaults so nothing
changes unless an installation opts in. The cnpg.io/cluster label
selector is added to constraints that carry none, and the constraints
replace the cluster-wide ones for this database when set.

Assisted-by: LLM
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
(cherry picked from commit dde75d6cf5)
2026-10-10 23:50:31 +00:00
Kirill Ilin f8766f7b03 feat(keycloak): let Keycloak and its database proxy spread across zones
Neither the Keycloak StatefulSet nor the keycloak-kms-proxy Deployment
exposed any placement, so the scheduler was free to put both replicas of
each in one failure domain. For Keycloak that is worse than it looks: a
StatefulSet does not replace a pod stuck on an unreachable node, so losing
that domain takes every replica for as long as it stays lost.

Expose affinity and topologySpreadConstraints for both, empty by default
so nothing changes unless an installation opts in, and give the proxy a
PodDisruptionBudget once it runs more than one replica.

Assisted-By: LLM
Signed-off-by: Kirill Ilin <stitch14@yandex.ru>
(cherry picked from commit 218384ed32)
2026-10-10 23:50:31 +00:00
Aleksei Sviridkin 57a139587f fix(cert-manager): enable the Gateway API solver in the controller
With the platform Gateway enabled, the ClusterIssuers in
cert-manager-issuers and the per-tenant Issuers rendered for
TenantGateway carry an http01.gatewayHTTPRoute solver, but the
controller only honours that solver when Gateway API support is
switched on, and the vendored chart leaves it off. Every HTTP-01
challenge behind the Gateway then fails with "gateway api is not
enabled" and no ACME certificate is issued.

Pass a ControllerConfiguration with enableGatewayAPI to the host
cert-manager through the component values of its platform Package.
The host always ships the Gateway API CRDs and orders cert-manager
after them, so the flag is safe on every variant.

It is not a default of the system/cert-manager chart: the same chart
is installed into tenant clusters, where the CRDs are an opt-in addon
and a controller started with Gateway API support and no CRDs exits
at startup. The tenant side keeps opting in on its own.

Signed-off-by: Aleksei Sviridkin <f@lex.la>
Assisted-by: LLM
(cherry picked from commit 76b9e55102)
2026-10-07 14:48:08 +00:00
Yan Bondarenko 07be46d37c fix(dashboard): drop the resource map ConfigMaps once the map is unreadable
React Query keeps the last successful list when a refetch fails. After the
resource map became forbidden or went away, the hook went on parsing that
old copy, so the ConfigMaps tab stayed with stale names, and a malformed
map kept its old error, instead of the tab going away as it does when the
map is unreadable from the start.

Assisted-by: LLM
Signed-off-by: Yan Bondarenko <202671653+yankawai@users.noreply.github.com>
(cherry picked from commit 8ce3f853af)
2026-10-07 11:00:42 +03:00
Yan Bondarenko 45bce211d1 fix(postgres): cap shared_buffers at the memory request
CloudNativePG rejects clusters whose shared_buffers exceeds the memory
request. Memory overcommit can put that request below both a quarter of
the limit and the 16MB floor.

Assisted-by: LLM
Signed-off-by: Yan Bondarenko <202671653+yankawai@users.noreply.github.com>
(cherry picked from commit 7af129b6a1)
2026-10-07 00:48:30 +03:00
Yan Bondarenko eb97d7a52c fix(postgres): cap the default shared_buffers at a quarter of the memory limit
The chart renders no shared_buffers, so PostgreSQL starts with its 128MB
default whatever the container gets. A full pool is the whole memory
limit on t1.nano and half of it on t1.micro, the default preset. The
pool is shared memory that the kernel cannot reclaim without swap, so
when a dump, index scans over a large table or a replica catching up
after a failover fill it, the instance is OOMKilled.

Instances below a 512Mi memory limit now default to a quarter of the
limit, at least 16MB. From 512Mi up a quarter is at least 128MB, so
those instances render exactly as before. shared_buffers needs a
restart, so on upgrade CloudNativePG restarts every instance below
512Mi that does not set it explicitly.

Assisted-by: LLM
Signed-off-by: Yan Bondarenko <202671653+yankawai@users.noreply.github.com>
(cherry picked from commit 0b39d7ea89)
2026-10-07 00:48:30 +03:00
Yan Bondarenko 7779208932 fix(mongodb): set the s3 bucket and prefix on the bootstrap restore
With bootstrap.enabled the chart rendered a PerconaServerMongoDBRestore
without backupSource.s3.bucket. The operator CRD requires that field, so
the API server rejected the restore and the HelmRelease failed. The prefix
was missing too, and it matters just as much. For a backupSource restore
the operator builds the PBM storage from backupSource.s3 alone and takes
only the backup name from backupSource.destination, so a restore without
the prefix would look for the backup at the bucket root.

The restore now takes the bucket and prefix from the same helpers that
fill the backup storage, so it reads from where the backups are written.
Both places quote the two values, so a numeric bucket or prefix stays a
string instead of making the resource invalid. The backup storage still
leaves out an empty prefix, so running releases keep the same object. A
destinationPath that names no bucket fails at render time instead of
reaching the operator with an empty bucket.

Assisted-by: LLM
Signed-off-by: Yan Bondarenko <202671653+yankawai@users.noreply.github.com>
(cherry picked from commit a6cf0e5ce4)
2026-10-06 21:30:34 +03:00
Yan Bondarenko 2610fb8565 fix(dashboard): show ConfigMaps listed in the application resource map
FoundationDB keeps its connection string in a ConfigMap that its operator
writes, and tenants may read it, but the console had no view for
ConfigMaps. Tenant roles grant ConfigMaps by name only, so the tab takes
the names from the application's resource map and reads each one with a
metadata.name field selector, which RBAC checks against resourceNames.
An application without a readable resource map shows no tab, while a
listed ConfigMap that cannot be read is reported instead of looking
empty.

On release-1.6 ApplicationDetailPage.test.tsx has none of the virtual
machine tab tests it sits next to on main, so only the ConfigMaps case
is added there.

Assisted-by: LLM
Signed-off-by: Yan Bondarenko <202671653+yankawai@users.noreply.github.com>
(cherry picked from commit 2fa7fea29b)
2026-10-04 12:07:43 +03:00
Yan Bondarenko 5b0682a073 fix(foundationdb): let tenants read the dashboard resource map
The resource map is the only object that names the connection ConfigMap
for a client such as the dashboard. It was rendered only with monitoring
enabled, and the tenant role could not read it, so a tenant session had
no way to find the ConfigMap it is allowed to read.

Assisted-by: LLM
Signed-off-by: Yan Bondarenko <202671653+yankawai@users.noreply.github.com>
(cherry picked from commit e3ae8033e6)
2026-10-04 12:07:13 +03:00
Yan Bondarenko afc51e425d fix(linstor): use severity warning instead of warn in piraeus-datastore alerts
Signed-off-by: Yan Bondarenko <202671653+yankawai@users.noreply.github.com>
(cherry picked from commit 3ade16a380)
2026-10-04 11:13:32 +03:00
Yan Bondarenko 95d7026c2e fix(nats): enable JetStream for the generated account
With users configured and jetstream.enabled true, the chart enables
JetStream on the server but generates account A without it, so every
JetStream call from those users fails with error 10039, "JetStream not
enabled for account". The generated account now gets jetstream: true
unless it already sets JetStream itself. nats-server matches config keys
case-insensitively and walks the account map in no fixed order, so a
JetStream key in any casing counts as set. Otherwise the account would
carry both keys and the server would apply either one, changing from
restart to restart.

Assisted-by: LLM
Signed-off-by: Yan Bondarenko <202671653+yankawai@users.noreply.github.com>
(cherry picked from commit 15b7092f3a)
2026-10-04 11:13:31 +03:00
Yan Bondarenko 948327d3f6 docs(tcp-balancer): say that whitelistHTTP needs a non-empty whitelist
The render now fails when whitelistHTTP is set with an empty whitelist,
so the values description tells users that before they hit the error.

Signed-off-by: Yan Bondarenko <202671653+yankawai@users.noreply.github.com>
(cherry picked from commit eee0596661)
2026-10-04 10:53:45 +03:00
Yan Bondarenko 0b9f0e75d7 test(tcp-balancer): check each frontend keeps its own whitelist rules
The accept and reject assertions matched anywhere in haproxy.cfg, so a
frontend that lost its reject rule stayed green as long as another
frontend still carried one. Without reject a non-matching connection
falls through to HAProxy's default accept, so that frontend is open to
everyone. Each assertion now anchors the acl, accept and reject lines to
the frontend they belong to.

Signed-off-by: Yan Bondarenko <202671653+yankawai@users.noreply.github.com>
(cherry picked from commit 6855bfb465)
2026-10-04 10:53:45 +03:00
Yan Bondarenko cc9e476c9e fix(tcp-balancer): rename backends and pin HAProxy so the chart starts on 3.3+
haproxy:latest now resolves to 3.3 and newer, where a backend named like
a frontend is a fatal config error, so every tcp-balancer pod fails at
config parse. Backends get a _backend suffix and the image follows the
chart appVersion on the 3.4 LTS line instead of a floating tag.

The whitelist rules render inside one guard. On the kubernetes and talos
frontends an empty whitelist means no filtering; whitelistHTTP with an
empty whitelist fails the render, because a security opt-in that quietly
became a no-op would not be noticed the way a crash is.

The unittest suite pins the rendered config for the default, whitelist
and failure cases and the image pin, so a template refactor cannot bring
the collision or the floating tag back.

Fixes #1966

Signed-off-by: Yan Bondarenko <202671653+yankawai@users.noreply.github.com>
(cherry picked from commit 12cc48d465)
2026-10-04 10:53:45 +03:00
Yan Bondarenko e708662e50 fix(platform): keep the legacy etcd-operator stopped after etcd adoption
Migration 50 scales the legacy etcd-operator to 0, adopts every legacy
etcd.aenix.io cluster with etcd-migrate and then scales the operator
back to 1. At that point it is still the legacy operator, and it has
nothing left to manage. Until a tenant's etcd HelmRelease reconciles the
new chart, Flux can upgrade it with the old one, which re-creates the
legacy EtcdCluster that etcd-migrate just orphan-deleted. The legacy
operator then reconciles it, re-creates the legacy StatefulSet and
rewrites the legacy etcd-headless Service, dropping the owner references
etcd-migrate pointed at the adopted EtcdMembers. When the new chart
prunes the legacy EtcdCluster, the garbage collector deletes the Service
with it, and the adopted members' etcd-<i>.etcd-headless names stop
resolving.

After a successful adoption the operator now stays at 0 until the
etcd-operator HelmRelease replaces the Deployment with the v1alpha2
operator later in the same upgrade. A failed or interrupted adoption
still restores it through the EXIT trap.

Assisted-by: LLM
Signed-off-by: Yan Bondarenko <202671653+yankawai@users.noreply.github.com>
(cherry picked from commit 6248d458ad)
2026-10-03 18:25:59 +03:00
Yan Bondarenko 0e76dda5ae feat(monitoring): add optional email alert delivery
Platform alerts need an email delivery path alongside Alerta without
exposing arbitrary namespace Secrets through tenant-controlled values.
SMTP credentials therefore use a fixed Secret name.

Alertmanager parses the addresses and connects to the SMTP host only
when it sends a notification, so a malformed value there drops alerts
instead of failing the release. The chart validates these fields when
it renders. Addresses must be literal dot-atom mailboxes, and a domain
literal must hold a dotted-quad IPv4 address, because IPv6 literal
syntax differs across the supported Go mail parsers. A bracketed
smarthost must be a valid IPv4 or IPv6 address, and its port must be
between 1 and 65535 without leading zeros. The repeat interval follows
the Alertmanager duration grammar and range, so a value that renders is
one Alertmanager loads.

Signed-off-by: Yan Bondarenko <202671653+yankawai@users.noreply.github.com>
Assisted-by: LLM
(cherry picked from commit 17aaf3e038)
2026-09-30 17:45:05 +03:00