Service Pod Architecture Changes for Self-Managed Environments

Frontend, JFBus, and JFmelt now run as standalone Kubernetes Deployments by default, and Helm requires a resolvable Join Key and Master Key for every installation.

Starting with 107.161.x Self-Managed release, the artifactory and artifactory-ha Helm charts run Frontend, JFBus, and JFmelt as standalone Kubernetes Deployments by default. This is a potentially breaking change if you use custom Helm values, are missing a Join Key or Master Key, or have network policies tuned for the previous single-pod layout.

These three services reached this state differently:

  • Frontend genuinely moved out of the Artifactory StatefulSet pod, where it previously ran as a container. It became available as an optional standalone Deployment in 107.146.x. From 107.161.x, enabled by default.
  • JFBus and JFmelt are newer platform services that were introduced directly as standalone Kubernetes Deployments — neither ever ran as a container inside the Artifactory StatefulSet pod. What changed for them in this release is that they are now enabled by default, where they previously required opting in.
ServiceStandalone Deployment introducedEnabled by default
FrontendSplit from the Artifactory StatefulSet containerChart update, 107.161.x
JFBusIntroduced directly as a standalone DeploymentChart update, 107.161.x
JFmeltIntroduced directly as a standalone DeploymentChart update, 107.161.x
❗️

Breaking Change Summary

Two things change by default in this release: Frontend, JFBus, and JFmelt now run as separate pods, and Helm now fails install/upgrade early if a Join Key and Master Key cannot be resolved. Review Breaking Changes and Customer Impact before upgrading.

Components Affected

ComponentHelm ValueDefault (this release)Deployment ModelNotes
Frontendfrontend.enabled, frontend.asPodtrue / trueStandalone DeploymentServes the JFrog Platform UI (jffe service ID). Previously ran as a container in the Artifactory StatefulSet pod; now split out and enabled by default.
JFBusjfbus.enabledtrueStandalone DeploymentPlatform event bus; used by Metadata and other services. Always a standalone Deployment since its introduction; now enabled by default instead of opt-in.
JFmeltjfmelt.enabledtrueStandalone DeploymentEvent collection and dispatch pipeline; requires jfbus.enabled: true and jfconnect.enabled: true, Pro only. Always a standalone Deployment since its introduction; now enabled by default instead of opt-in.
Artifactory coreartifactory.*unchangedStatefulSetRemaining microservices still run as containers in the Artifactory pod (splitServicesToContainers: true)

To disable any of these services (restoring Frontend to the Artifactory StatefulSet pod, or turning JFBus/JFmelt off entirely), see Configure Frontend, JFBus, and JFmelt Deployments.

New Pod Topology

flowchart TB
    subgraph FE["Frontend Pod"]
        F1["frontend + router + observability"]
    end
    subgraph JB["JFBus Pod"]
        J1["jfbus + router + observability"]
    end
    subgraph AF["Artifactory StatefulSet Pod"]
        A1["artifactory, metadata, event, jfconnect, router, observability, ..."]
    end
    subgraph JM["JFmelt Pod (Pro only)"]
        M1["jfmelt + router + observability"]
    end

    FE --> AF
    JB --> AF
    AF --> JM

Why These Services Run as Standalone Deployments

Frontend previously ran as a container inside a single Artifactory StatefulSet pod, alongside Artifactory and other microservices. That model had limits that motivated splitting Frontend out, and that also shaped JFBus and JFmelt as standalone services from their introduction:

  1. Coupled lifecycle — Restarting or upgrading one service restarted the entire pod.
  2. No independent scaling — Frontend could not be scaled separately under load.
  3. Resource contention — Services sharing one pod compete for that pod's CPU/memory limits.
  4. SaaS parity — SaaS already runs these as separate services; this release aligns Self-Hosted with that architecture.
  5. New platform services — JFBus and JFmelt are first-class services that need their own lifecycle, health checks, and horizontal pod autoscaling (HPA).
BenefitDescription
Independent scalingHPA on Frontend, JFBus, and JFmelt without touching Artifactory
Isolated upgradesRolling updates per service; fewer full-platform restarts
Better resilienceA failure in one service does not necessarily restart the whole platform
Resource tuningPer-service requests/limits in sizing profiles — see Hardware Sizing Matrix
Operational clarityClear pod-level health, logs, and metrics per service

Mandatory Join Key and Master Key

Helm now validates that a Join Key and Master Key can be resolved for every installation (unless keysPassedViaSystemyaml: true is set), because Frontend, JFBus, and JFmelt now run as independent deployments and each must authenticate to the platform at startup. If either key is missing, helm install/helm upgrade fails early with a descriptive error rather than deploying a pod that can't join the topology.

📘

Exact Error Names You May See

Depending on which key is missing, the chart's fail() message header reads ERROR: MISSING MANDATORY KEYS (both keys unresolved), ERROR: MISSING MASTER_KEY, or ERROR: MISSING JOIN_KEY (only one unresolved).

How to Provide Keys

Option 1 — Kubernetes Secret (recommended for production):

kubectl create secret generic artifactory-mandatory-keys -n <namespace> \
  --from-literal=master-key=${MASTER_KEY} \
  --from-literal=join-key=${JOIN_KEY}

helm upgrade --install artifactory jfrog/artifactory \
  --set global.masterKeySecretName=artifactory-mandatory-keys \
  --set global.joinKeySecretName=artifactory-mandatory-keys

Option 2 — Inline Helm values (dev/test only):

helm upgrade --install artifactory jfrog/artifactory \
  --set global.masterKey=${MASTER_KEY} \
  --set global.joinKey=${JOIN_KEY}

Option 3 — Keys already in system.yaml: If keys are already defined via artifactory.extraSystemYaml, artifactory.systemYaml, or systemYamlOverride under shared.security.joinKey/shared.security.masterKey, skip Options 1 and 2 and set:

helm upgrade --install artifactory jfrog/artifactory \
  --set keysPassedViaSystemyaml=true

Retrieving Existing Keys for an Upgrade

  • Join Key — In the JFrog Platform UI, go to Administration > Security > General > Connection Details, enter your password, and copy the Join Key. See Manage Keys for the full procedure.

  • Master Key — Retrieve it from a running Artifactory pod:

    export MASTER_KEY=$(kubectl exec -it <release>-artifactory-0 -n <namespace> -c artifactory -- cat /opt/jfrog/artifactory/var/etc/security/master.key)

Fresh installs can generate new keys instead of retrieving existing ones:

export MASTER_KEY=$(openssl rand -hex 32)
export JOIN_KEY=$(openssl rand -hex 32)

Breaking Changes and Customer Impact

ScenarioSymptomResolution
Upgrade without Join/Master KeyHelm fails with ERROR: MISSING MANDATORY KEYS (or the single-key variant)Provide keys per How to Provide Keys
Keys only in old artifactory.joinKey/artifactory.masterKey values but emptyValidation may still failSet global.joinKey/global.masterKey, or use Kubernetes Secrets
Keys already in system.yaml but the flag isn't setValidation fails despite keys existingSet keysPassedViaSystemyaml=true
OSS/JCR/CPP-CE customersJFmelt does not deployExpected — JFmelt requires a Pro license and jfconnect.enabled: true
Resource planningMore pods mean a higher baseline CPU/memory footprintReview Hardware Sizing Matrix; update requests/limits
Want the smallest footprint (Frontend in-pod, JFBus/JFmelt off)N/A — these are now the defaultsDisable individually: frontend.asPod: false, jfbus.enabled: false, jfmelt.enabled: false

splitServicesToContainers Requirement

From Artifactory 7.161.x, splitServicesToContainers: false is no longer supported. Setting it to false fails Helm validation with:

'splitServicesToContainers: false' is no longer supported.
Starting with releases from 7.161.x, the Helm chart no longer supports running all services in a single container.
Set 'splitServicesToContainers: true' to proceed.

splitServicesToContainers: true is the default and must remain enabled.

Support Troubleshooting Checklist

  1. Helm install/upgrade fails immediately — Check for a missing Join Key or Master Key; verify keysPassedViaSystemyaml is set if keys already exist in system.yaml.
  2. JFmelt not deploying — Confirm a Pro license, jfconnect.enabled: true, and jfbus.enabled: true.
  3. Frontend pod not starting — Check the waitForArtifactory init behavior and the Join/Master Key environment variables on the Frontend pod.

Related Topics

Frequently Asked Questions

plusFAQs
Q: Why does my Helm upgrade fail with a MISSING MANDATORY KEYS (or MISSING MASTER_KEY/MISSING JOIN_KEY) error?

A: Frontend, JFBus, and JFmelt now run as independent deployments and must each authenticate to the platform using a Join Key and Master Key. Helm validates that both keys are resolvable before proceeding (unless keysPassedViaSystemyaml: true). See How to Provide Keys to resolve this.

Q: I'm on OSS, JCR, or CPP-CE — why doesn't JFmelt deploy?

A: This is expected. JFmelt requires jfbus.enabled: true and jfconnect.enabled: true, and JFConnect itself is only available on Pro and above — the chart detects OSS/JCR/CPP-CE installations by their image repository name and disables JFConnect support there, which in turn keeps JFmelt from deploying.

Q: Can I go back to running Frontend in-pod and JFBus/JFmelt disabled?

A: Yes. Set frontend.asPod: false, jfbus.enabled: false, and jfmelt.enabled: false individually to restore Frontend to the Artifactory StatefulSet pod and turn JFBus/JFmelt off. splitServicesToContainers must remain true — from Artifactory 7.161.x, false is no longer supported.

Q: I get a Deployment.apps is invalid: spec.template.spec.containers[N].volumeMounts[M].name: Not found error — what's wrong?

A: You configured router.customVolumeMounts without a matching volume. The router now runs as a sidecar in the Frontend, JFBus, and JFmelt deployments, and each pod needs the volume defined locally — global.customVolumes/artifactory.customVolumes only add the volume to the Artifactory StatefulSet, not to these deployments. Add the corresponding volume under router.customVolumes using the same volume name referenced in router.customVolumeMounts, then re-run helm upgrade. Alternatively, define both global.customVolumeMounts and global.customVolumes so every pod gets the mount and its volume together. See Configure Frontend, JFBus, and JFmelt Deployments for the full pattern.

Q: I use an Oracle database — is there anything extra to configure for AppTrust and Platform Federation?

A: Yes. When using Oracle as your database, configure an initContainer to load the Oracle database drivers for AppTrust and Platform Federation before those services start.

Q: Does this affect Xray or Distribution?

A: No. This change is specific to the artifactory and artifactory-ha charts. Xray and Distribution are unaffected.



Did this page help you?