Skip to content

[netbox] release 5.1.0 — modernization, follow-up audit, Keycloak chart-managed block#124

Merged
firmansyahn merged 16 commits into
mainfrom
chore/netbox-260603
Jun 3, 2026
Merged

[netbox] release 5.1.0 — modernization, follow-up audit, Keycloak chart-managed block#124
firmansyahn merged 16 commits into
mainfrom
chore/netbox-260603

Conversation

@firmansyahn

Copy link
Copy Markdown
Collaborator

Summary

  • 5.1.0 modernization: bitnami commonst-common 0.1.21; subchart majors (postgresql 13→18, redis 19→27); helpers moved into templates/helpers/; Chart.lock committed with exact pins; new tls.certManager.*, gateway.tls.*, gateway.serviceEntry.*, externalDatabase.passwordless blocks (resolves Error on helm install caused by virtual service #56, netbox.redis.secretName rendered incorrectly #61, netbox: not possible to omit externalDatabase password #63, netbox: image parameters for housekeeping #64, netbox: How is externalRedis utilized? #65, netbox: not possible to omit Certificate when .Values.ingress.tls is present #79, netbox: .Values.image is not respected #83).
  • Follow-up audit on the same release cycle: CronJob housekeeping pod scope fixes (silently inheriting server's containerSecurityContext / extraEnvVarsCM / sidecars / extraVolumes / args); worker replica gate (was reading server HPA); LDAP bind-password key (was being written to superuser_password under LDAPBackend); external-redis Secret + projected-Secret mount no longer rendered for empty redis configs; worker pod-spec wired up (probes, lifecycle, dnsConfig, schedulerName, topologySpreadConstraints, etc.); HTTPRoute extraPaths modern Ingress v1 shape; redis subchart NetworkPolicy tightened to netbox-component pods only; Service ports 80/443 → 8080/8443; image coordinates moved from global.* to per-component blocks.
  • remoteAuth.keycloak.* chart-managed block: renders shared <release>-remoteauth Secret (with oidc-keycloak.yaml carrying every SOCIAL_AUTH_KEYCLOAK_* setting including the pipeline list) and <release>-keycloak-pipeline ConfigMap (with a templated keycloak_pipeline_roles.py). Mounted on the server pod only. Designed so sibling providers (oidc-azuread.yaml, oidc-google.yaml, oidc-okta.yaml, oidc-oidc.yaml) drop into the same shared Secret without renaming.
  • Docs & release plumbing: docs/auth.md rewritten with chart-managed Keycloak section, Azure AD / Google / Okta / generic OIDC walkthroughs, group-sync semantics table, troubleshooting. New docs/plugins.md for How to add / install a netbox plugin #62. ArtifactHub badge + artifacthub.io/changes + artifacthub.io/links annotations. README "Breaking Changes" extended to cover 5.0.5 → 5.1.0 grouped as "A. Subchart and helper migration" / "B. Default flips and latent-bug fixes". CHANGELOG [Unreleased] promoted to [5.1.0] - 2026-06-03 with link to the compare range.
  • helm-unittest grew from 10 suites / 91 tests → 12 suites / 137 tests. New Secret_test.yaml and ConfigMap_test.yaml; regression tests for every bug fixed in this branch.

Issues closed by this PR

#52, #56, #58 (couldn't reproduce on 5.1.0 — needs reporter retest), #61, #62, #63, #64, #65, #79, #83.

Test plan

  • helm lint charts/netbox — clean
  • helm template testrelease charts/netbox — renders 25 documents end-to-end
  • helm unittest charts/netbox — 12/12 suites, 137/137 tests pass
  • Render check with --set remoteAuth.keycloak.enabled=true — Secret <release>-remoteauth mounts under /run/config/extra/remote-auth/, ConfigMap <release>-keycloak-pipeline mounts at /opt/netbox/netbox/netbox/keycloak_pipeline_roles.py (server pod only — worker / housekeeping skip)
  • Render check default + every breaking-change toggle (tls.enabled, gateway.enabled, redis.enabled=false, externalDatabase.passwordless, modern Ingress v1 extraPaths)
  • ct lint --target-branch main --chart-dirs charts — passed after maintainer-name fix (commit ae22a17)

Reviewers' attention

Two pre-existing bugs surfaced and fixed while writing tests — flagging because they affect existing installs:

  1. LDAP bind password key fix. Anyone who ran 5.0.x with remoteAuth.backends: [netbox.authentication.LDAPBackend] was getting their bind password written to the superuser_password Secret data key (clobbering the actual superuser password). 5.1.0 writes it under the correct ldap_bind_password key. Rotate the bind password after upgrade. Documented in README → Breaking Changes → From 5.0.10 to 5.1.0.
  2. Service ports default change. service.ports.http: 80 → 8080, service.ports.https: 443 → 8443. Ingress / Gateway external listeners still terminate on 80/443; the change is on the in-cluster Service port. Clients hitting <release>-netbox:80 directly (port-forwards, peer Services in the same cluster) need to update.

…H issue fixes)

Bug fixes
- #83: _images.tpl `default A B` arg order swapped so per-component
  imageRoot.* wins over global.* (silently ignored before)
- #61: netbox.redis.secretName / netbox.databaseSecretName no longer
  conflate top-level .Values.existingSecretName into the redis/db helper
- #56: istio capability guards rewritten to handle string-"false",
  boolean-false, and "<no value>" returns uniformly
- #63: new externalDatabase.passwordless toggle skips db_password
  projected mount + DATABASE["PASSWORD"] loader (CloudSQL IAM auth)
- #79: chart-managed Certificate resource is now auto-rendered based on
  cert-manager API detection; opt out via tls.certificatesSecret
- ServiceMonitor.yaml `merge.Values...` typo (metrics/ + worker/) replaced
  with st-common.tplvalues.merge include
- istio/ServiceEntry.yaml hardcoded hosts (netbox.dev, github.com,
  api.github.com) removed; opt-in via gateway.serviceEntry.{enabled,hosts}

Modernization
- All template helper references migrated common.* -> st-common.*
  (39 files). Per-resource capability renames: certmanagerCertificate,
  istioGateway / istioVirtualService / istioServiceEntry,
  coreosMonitoringServiceMonitor / coreosMonitoringPrometheusRule,
  networkingGatewayHTTPRoute.
- bitnami common dep removed from Chart.yaml; st-common 0.1.21 from
  oci://ghcr.io/startechnica/charts (unaliased).
- postgresql 13.x.x -> 18.7.0; redis 19.x.x -> 27.0.0; both pinned exactly.
  Image-major bumps documented in README §Upgrading.
- Chart.lock committed (per bitnami catalog deprecation fix).
- Helpers moved into templates/helpers/ subdir via `git mv`.
- TLS auto-detection: when tls.enabled (or ingress.tls) AND cert-manager
  API present AND no tls.certificatesSecret, Certificate auto-renders.
  Legacy flags tls.autoGenerated, tls.certManager.create, and
  tls.autoGenerator.certManager.* marked DEPRECATED (no longer consulted).
- Additive blocks: gateway.tls.*, gateway.serviceEntry.*,
  externalDatabase.passwordless.
- Chart.yaml top-level keys sorted ascending.

Docs
- README parameter table moved to just before License.
- README install examples switched HTTPS repo -> OCI
  (oci://ghcr.io/startechnica/charts/netbox).
- New CHANGELOG.md covering every release 5.0.0 -> 5.1.0.
- New §Upgrading subsection for 5.1.0 with 6 numbered migration steps.

Verification
- helm lint .  -> 0 chart(s) failed
- helm template testrelease . -> 1730 lines (default), 1784 lines
  (with --set tls.enabled=true --api-versions cert-manager.io/v1/Certificate),
  expected resource counts; passwordless mode skips external-db Secret +
  db_password mounts as designed.
… auto-detect

Park 5.1.0 release signal — strip artifacthub.io/changes annotation from
Chart.yaml and move the 5.1.0 CHANGELOG entry under [Unreleased]. The
version field stays at 5.1.0 as the next-target, but the chart is not
yet release-ready.

Gateway refactor (freeradius pattern)
- Replace `gateway.gatewayApi.create` with `gateway.implementation`
  selector (gateway-api | istio) and add `gateway.infrastructure: envoy`
  knob for EnvoyProxy data-plane attachment.
- Add nested `gateway.gateway.{create,name,namespace}`,
  `gateway.envoyProxy.{create,name}`, `gateway.listenerSet.*`,
  `gateway.referenceGrant.*`, `gateway.httpRoute.parentRefs`,
  `gateway.virtualService.{tls,tcp}` blocks.
- Add `gateway.hostnames: []` — decouples gateway-side hosts from
  `ingress.hostname` / `ingress.extraHosts` (falls back when empty).
- Rename `templates/gatewayApi/` -> `templates/gateway-api/`.
- Rewrite Gateway.yaml + HTTPRoute.yaml; add new EnvoyProxy.yaml,
  ReferenceGrant.yaml, ListenerSet.yaml under gateway-api/.
- Rewrite istio Gateway.yaml + VirtualService.yaml + ServiceEntry.yaml
  to gate on `implementation` selector and use the new hostnames helper.
- New helpers in `templates/helpers/_gateway.tpl`:
  `netbox.gateway.{fullname,namespace,hostnames,tlsSecretName,
  envoyProxy.name,envoyProxy.create,routeParentRefs}`.

TLS auto-detection (deprecate-don't-delete)
- `netbox.tls.certManager.create` now auto-detects cert-manager API
  presence rather than reading a flag. Renders Certificate when
  (tls.enabled OR ingress.tls) AND cert-manager CRD present AND
  `tls.certificatesSecret` empty. Opt-out path: pre-create the Secret +
  set tls.certificatesSecret.
- Mark `tls.autoGenerated`, `tls.certManager.create`,
  `tls.autoGenerator.certManager.*` as [DEPRECATED - no longer consulted],
  slated for 6.0.0.

Helper file split
- Move database helpers (netbox.postgresql.fullname,
  netbox.database{Host,Port,Name,User,Secret*,Password}, validateValues.database)
  -> `templates/helpers/_database.tpl`.
- Move redis helpers (netbox.redis.fullname, redis.{secretName,
  secretPasswordKey,password,auth.enabled,host,port},
  {cachingRedis,tasksRedis}.{secretPasswordKey,password,host,port})
  -> `templates/helpers/_redis.tpl`.
- Move gateway helpers (see above) -> `templates/helpers/_gateway.tpl`.

Helper / values cleanup
- Drop dead helpers: netbox.{name,chart,labels,labels.standard,
  selectorLabels}. Zero external callers; only chained into each other.
  Single external `netbox.name` callsite (NOTES.txt) -> st-common.names.name.
- Drop tiny image wrappers (netbox.{image,worker.image,housekeeping.image,
  init-dirs.image}) and inline `include "netbox.images.image"` at each
  callsite (5 sites).
- Mass-replace `include "netbox.fullname"` -> `include "st-common.names.fullname"`
  across 24 files (54 occurrences). Remove local netbox.fullname helper.
- Strip redundant `(ne $apiVer "<no value>")` guards from 10 capability
  templates — `include` of a defined template never returns the literal
  "<no value>" string, so the extra clause is dead.

Resource presets
- Add `resourcesPreset: "none"` to top-level, `worker`, and `housekeeping`
  blocks. Server/worker/housekeeping containers fall through to
  `st-common.resources.preset` when `resources` is empty and
  `resourcesPreset != "none"`.

Documentation
- Inline comments in values.yaml explaining how externalRedis fans out
  to tasksRedis + cachingRedis vs how per-component overrides take
  precedence (addresses #65).
- SPDX/copyright header added to all 39 template files (skipping
  NOTES.txt which is rendered as plain text to users).

Repo hygiene
- Normalize CRLF -> LF and ensure trailing newline on all chart files.
- Chart.yaml top-level keys remain sorted ascending.

Verification
- helm lint . -> 0 chart(s) failed
- helm template testrelease . -> 1734 lines (default)
- helm template ... --set gateway.enabled=true --set gateway.gateway.create=true
  --api-versions cert-manager.io/v1/Certificate (and gateway-api CRDs)
  -> Gateway / HTTPRoute / EnvoyProxy + Certificate render cleanly
- helm template ... --set gateway.implementation=istio
  --api-versions networking.istio.io/v1/{Gateway,VirtualService}
  -> Istio Gateway + VirtualService render cleanly
10 helm-unittest suites (78 tests) covering Deployment/Service,
worker + housekeeping, HPA, Ingress, Gateway API + Istio
implementations, metrics, NetworkPolicy, PVCs, and TLS / cert-manager
auto-detect. Adds values.schema.json for chart input validation.
…ages

Fixes 4 hard bugs uncovered by a values-vs-templates audit:
- allowedHostsIncludesPodIp (lowercase p) typo in ConfigMap/netbox.yaml
  and Deployment.yaml meant the POD_IP env-var path never activated.
- Certificate.yaml gateway-side block read non-existent .Values.gateway.namespace
  (real key is gateway.gateway.namespace); rewired to the netbox.gateway.namespace
  helper and gated on app-ns vs gateway-ns mismatch.
- NOTES.txt iterated .Values.ingress.hosts (legacy) instead of
  ingress.hostname + ingress.extraHosts; URLs now render.
- CronJob.yaml restored lowercase .Values.timezone / .Values.housekeeping.timezone
  to match Worker_test expectations.

Documents ~25 previously-undeclared optional inputs in values.yaml (timezone,
terminationGracePeriodSeconds, extraEnvVarsCMs, existingConfigmap, initdbScripts,
initdbScriptsConfigMap, housekeeping.{timezone,ttlSecondsAfterFinished},
worker.{terminationGracePeriodSeconds,annotations,podDisruptionBudget.enabled},
email/cachingRedis/tasksRedis.existingSecretName, externalRedis.annotations,
superuser.existingSecretApiTokenKey, metrics.{labels,podAnnotations,podLabels,
serviceMonitor.annotations}, persistence.dataSource, serviceAccount.imagePullSecrets).
Adds deprecation markers for housekeeping.timeZone, worker.podDisruptionBudget.create,
metrics.service.port, redisWait.{pullPolicy,pullSecrets} (now nested under image).

Bitnami image refresh: moves git + os-shell from docker.io to public.ecr.aws,
bumps redis 8.6.2 -> 8.6.3, os-shell to 12-debian-12-r65, git to 2.54.0-debian-12-r3.

Tests: 89/89 pass; GatewayAPI_test now sets gateway.{gatewayClassName,infrastructure}
explicitly instead of relying on defaults, and Worker_test gained housekeeping
ttlSecondsAfterFinished / timezone / suspend / command coverage.
…p mapping

Factors out _client_roles / _realm_roles helpers in the Keycloak pipeline
example and adds a GROUP_SOURCE switch so set_groups can pull Django groups
from `resource_access[CLIENT_ID].roles`, `realm_access.roles`, or the
`groups` claim depending on which Keycloak mapper the client has.
…bes/lifecycle wired + auth.md provider expansion

CronJob housekeeping was silently inheriting the server pod's scope on
five fields. Fixed `containerSecurityContext`, `args` fallback,
`envFrom` (now reads housekeeping.extraEnvVarsCM / extraEnvVarsSecret /
extraEnvVarsSecrets plural), `sidecars`, `extraVolumes`. Added
`imagePullPolicy` line (was missing). Defaulted housekeeping
`readOnlyRootFilesystem: true` to match server/worker.

Worker Deployment was gating replicas on `.Values.autoscaling.enabled`
(server HPA) instead of `worker.autoscaling.enabled` — enabling server
HPA silently stripped the worker's replica count. Same `extraVolumes`
top-level bug present in worker/Deployment.yaml and worker/Job.yaml.

Worker pod spec now renders `dnsConfig`, `dnsPolicy`,
`enableServiceLinks`, `schedulerName`, `shareProcessNamespace`,
`topologySpreadConstraints`, `revisionHistoryLimit`, `minReadySeconds`,
`lifecycleHooks`. Probes (startup/liveness/readiness + custom*
variants) now render — default is `exec: pgrep -f "manage.py rqworker"`
since rqworker has no HTTP endpoint.

Two pre-existing bugs surfaced and fixed while writing tests:
- `netbox.initdbScriptsCM` helper referenced in Deployment.yaml:385 was
  never defined — would crash `helm template` for anyone setting
  `initdbScripts` or `initdbScriptsConfigMap`.
- Secret/netbox.yaml under LDAPBackend wrote `remoteAuth.ldap.bindPassword`
  to a key named `superuser_password` (via
  `netbox.superuser.secretPasswordKey`), clobbering the actual superuser
  password. Now uses `netbox.remoteAuth.ldap.secretBindPasswordKey` and
  gates on `existingSecretName`.

helm-unittest: 10 → 12 suites, 91 → 128 tests. New Secret_test and
ConfigMap_test suites; Worker_test expanded with regression tests for
every fix above plus Job / extraWorkers / PodDisruptionBudget / extraDeploy.

docs/auth.md: added group-sync semantics table (defaultGroups vs
groupSyncEnabled, groupSeparator, superuserGroups, autoCreateUser/Groups),
Azure AD / Entra ID example with GUID→name mapping, Google Workspace,
Okta with claim-filter notes, generic OIDC, and a troubleshooting
section covering 403-on-login, group-sync no-shows, redirect_uri table,
token-refresh, and LDAP bind-password rotation.
Empty default is more correct — the field is only consulted when the
in-chart redis subchart is disabled, and silently defaulting to
localhost let bad configs (no redis subchart, no externalRedis.host
set) appear to render but point at a non-existent in-pod redis.
Previously the chart always rendered the external-redis Secret as long
as the redis subchart was disabled and no existingSecretName was set —
even when the user hadn't actually configured any external redis target.
This produced a Secret with empty/null password keys that pointed
nowhere.

Now the Secret only renders when at least one of `externalRedis.host`,
`externalRedis.password`, `tasksRedis.password`, or `cachingRedis.password`
is set. Broader than the literal `externalRedis.host AND .password` ask
because tasksRedis-only / cachingRedis-only setups (where the sub-block
is configured directly without filling externalRedis.*) need the Secret
to render so the rqworker and main app can read their respective
passwords.

Regression tests added: skip with no redis at all, render with only
externalRedis.host, render with only tasksRedis.password.
…get is configured

Companion to the prior commit. Pods were referencing
`netbox.redis.secretName` in their projected volumes even when the
corresponding Secret had been suppressed for being empty — that would
have left the pod stuck in ContainerCreating with
"MountVolume.SetUp failed for volume … secret not found."

New helper `netbox.redis.mountSecret` returns truthy when any of:
- `redis.enabled` (subchart owns the Secret)
- any `existingSecretName` (BYO Secret already in cluster)
- any password set on `externalRedis` / `tasksRedis` / `cachingRedis`
- `externalRedis.host` set (covers the rare host-set-password-unset case)

Wired into the four pod templates (Deployment, worker/Deployment,
worker/Job, CronJob).

Regression tests cover: subchart-enabled mount, mount suppressed when
nothing configured, BYO existing-secret mount.
… image blocks

The global image fields were the only place where the actual image
coordinates lived; the server, worker, and housekeeping image blocks
all defaulted to empty strings and relied on the helper to fall through
to global.image*. That made the precedence chain harder to read and
forced anyone overriding a single component to either set both layers
or remember the fall-through order.

Now each of server / worker / housekeeping declares its own
registry/repository/tag explicitly (docker.io / netboxcommunity/netbox
/ v3.7.8-2.8.0). global.imageRegistry / imageRepository / imageTag are
empty by default and serve their canonical role — a single knob to
override registry or tag across all three components at once. The
per-component value wins per #83's precedence helper, so this is a
no-op rename of where the same string lives.

Verified: helm template output is byte-identical
("docker.io/netboxcommunity/netbox:v3.7.8-2.8.0" on server, worker,
housekeeping); 134 helm-unittest tests pass.
…mponents

Bitnami redis defaults `networkPolicy.enabled: true` but
`allowExternal: true` — which renders an NP that accepts ingress from
anywhere on 6379. That's effectively no policy.

Flip `redis.networkPolicy.allowExternal: false` and add an `extraIngress`
rule that scopes 6379 ingress to pods carrying
`app.kubernetes.io/part-of=netbox` AND a component label of `server`,
`worker`, or `housekeeping` — i.e. exactly the three netbox workloads
this chart deploys. Cross-namespace clients (shared monitoring, etc.)
must opt in via `redis.networkPolicy.ingressNSMatchLabels` or by
extending `extraIngress`.

Verified via `helm template`: the redis NP now emits the default
`<release>-redis-client: "true"` allow plus our component-label rule,
and no longer accepts arbitrary cluster ingress.
`ct lint` validates each maintainer by hitting
`https://github.com/<name>`. The full name "Firmansyah Nainggolan"
404s; the actual GitHub username is `firmansyahn`, which every other
chart in this repo already uses. Switched netbox to match and aligned
the list indentation to the repo convention.
…il-pointer)

The HTTPRoute template was dereferencing `.backend.serviceName` /
`.backend.servicePort` on every `ingress.extraPaths` entry. Those keys
belong to the legacy v1beta1 Ingress shape; modern Ingress v1 uses
`.backend.service.name` and `.backend.service.port.{number,name}`. A
user passing the v1 shape (which is what every kubectl-generated
Ingress emits since K8s 1.19) crashed the chart with:

  nil pointer evaluating interface {}.serviceName

The Ingress template never noticed because it splices extraPaths
through `toYaml` and lets the user pass any v1/v1beta1 shape. HTTPRoute
has no such pass-through — it needs an explicit name+port — so we now
translate both shapes:

- v1 modern: read `backend.service.name` + `backend.service.port.number`
- v1beta1 legacy: read `backend.serviceName` + `backend.servicePort`
- entries that only carry a port `name` (no number) get skipped, since
  HTTPRoute backendRefs require a numeric port and we can't do a
  Service lookup at template time

Regression tests added for all three cases.
…IP -> clusterIPs

- remove unused service.port (legacy single port); Service/NOTES use service.ports.http
- remove service.http.enabled gate; http port always rendered
- replace singular service.clusterIP with dual-stack service.clusterIPs list
- remove orphan singular service.nodePort (only nodePorts.http/https are wired)
- tests: expect service ports 8080/8443 (Application/GatewayAPI/Istio)
…g updates

Materializes a typical Keycloak SSO setup from a small values block so
users no longer need to copy-paste the long extraConfig/extraDeploy
walkthrough from docs/auth.md.

Values block under `remoteAuth.keycloak.*`:
- `enabled`, `clientId`, `clientSecret`, `realmUrl`, `publicKey`
- `groupSource` (client | realm | groups) + `isStaffRole` /
  `isSuperuserRole` + `extraGroupMappings` drive the auto-generated
  pipeline functions
- `scopes` (replaces social-auth default), `pipelines` (full ordered
  pipeline list), `audienceMapperName` (doc-only)
- `existingPipelineConfigMap{,Key}` escape hatch for users who need a
  fully-custom pipeline file

Resources rendered when enabled:
- Shared `<release>-remoteauth` Secret (templates/Secret/remote-auth.yaml)
  with key `oidc-keycloak.yaml` carrying every SOCIAL_AUTH_KEYCLOAK_*
  setting (KEY, SECRET, PUBLIC_KEY, AUTHORIZATION_URL, ACCESS_TOKEN_URL,
  SCOPE, PIPELINE, JSONFIELD_ENABLED). Single Secret per release —
  future providers (azuread / google / okta / oidc) get their own
  `oidc-<provider>.yaml` keys without renaming the resource.
- `<release>-keycloak-pipeline` ConfigMap with templated
  `keycloak_pipeline_roles.py`: `set_role()` and `set_groups()` rendered
  from the values above. `KEYCLOAK_EXTRA_GROUP_MAPPINGS` translates
  Keycloak role names to Django Group names where they differ.

Mounted only on the server pod (templates/Deployment.yaml). The
social-auth pipeline runs only at web login — worker (rqworker) and
housekeeping (manage.py housekeeping) load configuration.py but never
execute the pipeline, so the file is unneeded there.

Mount points:
- Secret as a directory at /run/config/extra/remote-auth/ — each key
  becomes a file picked up by the existing configuration.py
  /run/config/extra/<provider>/*.yaml glob via globals().update()
- ConfigMap at /opt/netbox/netbox/netbox/keycloak_pipeline_roles.py so
  the pipeline step `netbox.keycloak_pipeline_roles.set_role` resolves
  as a normal Python import

New helpers under templates/helpers/_helpers.tpl:
- netbox.socialAuth.{secretName,secretVolume,secretVolumeMount,enabled}
- netbox.keycloak.{pipelineConfigMapName,pipelineVolume,pipelineVolumeMount}

Also in this commit:

- HTTPRoute now translates the modern Ingress v1 extraPaths shape
  (`backend.service.{name,port.number}`) in addition to the legacy
  v1beta1 form. Previously crashed with a nil-pointer dereference on
  `.backend.serviceName`. Entries that only carry a port name (no
  resolvable number) are skipped. Explicit `group: ""` / `kind: Service`
  emitted on every backendRef so rendered output matches what the API
  server returns on GET.

- docs/auth.md gains a "Configuring Keycloak (chart-managed)" section
  ahead of the existing manual walkthrough (renamed to
  "Configuring Keycloak (manual via extraConfig)") with a groupSource
  decision table, pipeline-override and bring-your-own-ConfigMap
  examples, and a "when to use the manual recipe instead" callout.

- Chart.yaml adds artifacthub.io/changes (17 one-liners) and
  artifacthub.io/links (CHANGELOG + README §Upgrading), so the
  ArtifactHub release page reflects the work shipped in 5.1.0.

- README gets an ArtifactHub badge under the title (matching the
  freeradius/adminer convention) and a new "#7. New
  remoteAuth.keycloak.* chart-managed block" step in
  Upgrading → To 5.1.0.

- CHANGELOG [Unreleased] extended with all session-cycle additions:
  the Keycloak block, worker pod-spec wire-up, hardening (housekeeping
  readOnlyRootFilesystem), Service port 8080/8443, global.image* move,
  helm-unittest growth to 12/137, plus every patch-cycle bug fix
  (CronJob housekeeping-scope, worker replica gate, LDAP key, etc.).
Promotes the CHANGELOG [Unreleased] block to [5.1.0] - 2026-06-03 and
fills the last gaps in issue citations under that release block:

- #52 — the housekeeping.extraVolumes scope fix in this branch now
  references the original indent fix from PR #53.
- #58 — added a "possibly addresses, couldn't reproduce on 5.1.0" note
  on the configuration.py cleanups; asking the reporter to retest.
- #62 — new docs/plugins.md walks through the derived-image recipe
  (Dockerfile overlay → pin all three image: / worker.image: /
  housekeeping.image: tags at it → enable via plugins: / pluginsConfig:),
  plus a post-install,post-upgrade migration Job pattern via extraDeploy,
  static-files note, and troubleshooting (ModuleNotFoundError causes,
  env-var injection, version-compat). README gains an "Installing
  plugins" section linking the new doc.
- #64 — annotated as a side-effect of the #83 image precedence fix.

All ten addressable issues from this release scope (#52, #56, #58, #61,
#62, #63, #64, #65, #79, #83) now have at least one citation in the
[5.1.0] section.

CHANGELOG link footer updated: [Unreleased] -> [5.1.0] pointing at the
compare range netbox-5.0.10...netbox-5.1.0.
@firmansyahn firmansyahn merged commit d384b7b into main Jun 3, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Error on helm install caused by virtual service

1 participant