ARTIFACTORY: Installing JFrog Platform with NGINX Ingress Controller

Products
Frog_Artifactory
Content Type
Installation_Setup
AuthorFullName__c
Ilan Klein, Anjali Singh, Evgeny Nikolin
articleNumber
000006832
FirstPublishedDate
2026-01-22T10:02:46Z
lastModifiedDate
2026-07-16

ARTIFACTORY: Installing JFrog Platform with NGINX Ingress Controller

Introduction
This document outlines the steps and configuration required to install JFrog Platform using the official NGINX Ingress Controller. With the Kubernetes community ingress-nginx controller being deprecated, this guide validates nginx/nginx-ingress as a supported alternative and highlights the necessary changes from the previous ingress setup. It covers the installation of the NGINX Ingress Controller, updated Artifactory Helm configurations for TLS, non-TLS, and Docker subdomain deployments, and key considerations for a successful migration.
This document describes:
  • Required changes compared to the old ingress configuration
  • Installation of NGINX Ingress Controller
  • Artifactory Helm values for TLS, non-TLS, and Docker subdomain setups

Resolution
Old Ingress Configuration (Reference)
The following snippet represents the earlier ingress configuration that relied on Kubernetes ingress-nginx annotations:
artifactory:
  nginx:
    enabled: false

  ingress:
    enabled: true
    defaultBackend:
      enabled: true
    hosts:
      - <nginx-ingress-svc-external-hostname or dns hostname>
    routerPath: /
    artifactoryPath: /artifactory/
    className: "nginx"
    annotations:
      nginx.ingress.kubernetes.io/proxy-body-size: "0"
      nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
      nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
      nginx.ingress.kubernetes.io/configuration-snippet: |
        rewrite ^/(v2)/token /artifactory/api/docker/null/v2/token;
        rewrite ^/(v2)/([^\/]*)(/.*) /artifactory/api/docker/$2/$1$3;
    tls:
    - secretName: nginx-tls
      hosts:
        - <nginx-ingress-svc-external-hostname or dns hostname>


Install NGINX Ingress Controller
Note
This step is performed and managed by the customer. JFrog does not install, configure, or manage, and has no control over it.

Install the official NGINX Ingress Controller using Helm. Snippet support must be explicitly enabled.
helm repo add nginx https://helm.nginx.com/stable
helm repo update

helm install nginx-ingress nginx/nginx-ingress \
  --set controller.enableSnippets=true \
  -n nginx-ingress --create-namespace

Note
This controller uses `nginx.org/*` annotations instead of `nginx.ingress.kubernetes.io/*`. See the [F5 NGINX IC documentation on snippets] for details.

Note
The example above installs the controller with the default ingress class name `nginx`. If a custom class name is used (e.g., via `--set controller.ingressClass=nginx-f5`), ensure the `className` field in the Artifactory `values.yaml` is updated to match.


Install JFrog Platform
For full installation instructions, refer to the JFrog Platform Helm installation documentation.

The `ingress:` configuration examples below apply to both the standalone Artifactory chart (`jfrog/artifactory`) and the full JFrog Platform chart (`jfrog/jfrog-platform`). The ingress block is identical in both. Pass the relevant snippet as part of your `values.yaml` when running your `helm install` or `helm upgrade` command.

Option 1: With TLS Enabled
artifactory:
  nginx:
    enabled: false

  ingress:
    enabled: true
    defaultBackend:
      enabled: true
    hosts:
      - <nginx-ingress-svc-external-hostname or dns hostname>
    routerPath: /
    artifactoryPath: /artifactory/
    className: "nginx"
    annotations:
      nginx.org/client-max-body-size: "0"
      nginx.org/proxy-read-timeout: "600"
      nginx.org/proxy-send-timeout: "600"
      nginx.org/location-snippets: |
        rewrite ^/(v2)/token /artifactory/api/docker/null/v2/token;
        rewrite ^/(v2)/([^\/]*)(/.*) /artifactory/api/docker/$2/$1$3;
    tls:
    - secretName: nginx-tls
      hosts:
        - <nginx-ingress-svc-external-hostname or dns hostname>

Option 2: Without TLS
artifactory:
  nginx:
    enabled: false

  ingress:
    enabled: true
    defaultBackend:
      enabled: true
    hosts:
      - <nginx-ingress-svc-external-hostname or dns hostname>
    routerPath: /
    artifactoryPath: /artifactory/
    className: "nginx"
    annotations:
      nginx.org/client-max-body-size: "0"
      nginx.org/proxy-read-timeout: "600"
      nginx.org/proxy-send-timeout: "600"
      nginx.org/redirect-to-https: "false"
      nginx.org/location-snippets: |
        rewrite ^/(v2)/token /artifactory/api/docker/null/v2/token;
        rewrite ^/(v2)/([^\/]*)(/.*) /artifactory/api/docker/$2/$1$3;


Option 3: With Docker Subdomain Access (TLS)
Use this configuration to allow Docker clients to access Artifactory using the subdomain access method, where each Docker repository is exposed on its own subdomain (e.g., `<repo>.artifactory.example.com`).

The F5 NGINX IC achieves subdomain routing using:
  • `nginx.org/server-snippets` — a regex on the `$host` variable with a named capture group to extract the repository name from the subdomain.
  • `nginx.org/location-snippets` — rewrite rules to route Docker API requests to the correct Artifactory Docker repository, plus the `X-JFrog-Override-Base-Url` header so Artifactory generates correct Docker registry URLs in responses.
Additional Prerequisites
Before applying this configuration, ensure the following are in place in addition to the base prerequisites above:
  1. A wildcard TLS certificate covering `*.artifactory.example.com`.
  2. A wildcard DNS record pointing `*.artifactory.example.com` to the Ingress Controller's external IP.
artifactory:
  nginx:
    enabled: false

  ingress:
    enabled: true
    defaultBackend:
      enabled: false
    hosts:
      - artifactory.example.com
      - '*.artifactory.example.com'
    routerPath: /
    artifactoryPath: /artifactory/
    className: "nginx"
    annotations:
      nginx.org/client-max-body-size: "0"
      nginx.org/proxy-read-timeout: "2400s"
      nginx.org/proxy-send-timeout: "2400s"
      nginx.org/proxy-buffers: "40 128k"
      nginx.org/proxy-busy-buffers-size: "128k"
      nginx.org/server-snippets: |
        set $repo "docker";
        if ($host ~* "^(?<captured_repo>.+)\.artifactory\.example\.com$") {
          set $repo $captured_repo;
        }
      nginx.org/location-snippets: |
        rewrite ^/(v1|v2)/(.*) /artifactory/api/docker/$repo/$1/$2 break;
        rewrite ^/(v1|v2)/ /artifactory/api/docker/$repo/$1/ break;
        proxy_set_header X-JFrog-Override-Base-Url $scheme://$host;
    tls:
      - secretName: artifactory-tls
        hosts:
          - artifactory.example.com
          - "*.artifactory.example.com"

Make sure to replace `artifactory.example.com` with the actual DNS hostname or service name. Escape dots in the regex accordingly (e.g., `artifactory\.example\.com`).

Notes

  • The `hosts` and `tls` sections must include both the base domain (`artifactory.example.com`) and the wildcard (`*.artifactory.example.com`).
  • `defaultBackend` is set to `false` because the wildcard host entry handles all subdomain requests. A separate default backend is not needed.
  • The default `$repo` value (`"docker"`) is used when accessing the base domain directly (without a subdomain prefix). Change this to match your default Docker repository name if different.
  • The timeouts in this option (`2400s`) are set higher than Options 1 and 2 (`600`) to accommodate large Docker image layer push/pull operations.
  • The `X-JFrog-Override-Base-Url` header ensures Artifactory returns correct Docker registry URLs in responses. Without it, Docker clients may receive redirect URLs pointing to the wrong hostname. See the JFrog HTTP Settings documentation for more details
Explanation on the Annotations Used
Annotation
Description
nginx.org/client-max-body-size: "0"
Removes the request body size limit (allows unlimited upload size)
nginx.org/proxy-read-timeout: "600"
Sets the maximum time (in seconds) NGINX waits to read a response from the backend
nginx.org/proxy-send-timeout: "600"
Sets the maximum time (in seconds) NGINX waits to send a request to the backend
nginx.org/redirect-to-https: "false"
Disables automatic redirection from HTTP to HTTPS
nginx.org/location-snippets
Injects custom NGINX rewrite rules to route Docker v2 registry and token requests to Artifactory.
nginx.org/server-snippets
Injects custom NGINX server-level directives; used here to extract the Docker repository name from the request subdomain.
nginx.org/proxy-buffers / nginx.org/proxy-busy-buffers-size
Tune the NGINX proxy buffer sizes; recommended for large Docker layer transfers.


Validate JFrog Platform Access
Verify that the JFrog Platform is reachable through the Ingress by calling the [Router health check endpoint] (see here), which reports the health of all platform services (not just Artifactory):
curl https://<hostname>/router/api/v1/system/health
A 200 response means all the services are healthy.
Notes & Considerations
  • Docker registry traffic requires the rewrite rules defined in `location-snippets`.
  • `controller.enableSnippets=true` is mandatory for custom rewrite rules in all configurations.
  • Ensure `className: nginx` matches the ingress class created by the controller.
  • Ensure `className: nginx` matches the ingress class name used when the controller was installed. If a custom class name was used, update `className` in the Artifactory `values.yaml` accordingly.
  • The timeouts in Options 1 and 2 are set to `600` seconds (sufficient for standard artifact operations). Option 3 uses `2400s` to accommodate large Docker image layer push/pull operations, which can take significantly longer.
  • For production, CA-signed certificates are recommended instead of self-signed ones.
  • For Docker subdomain access (Option 3), a wildcard TLS certificate and wildcard DNS record are required in addition to the base prerequisites.
  • The `X-JFrog-Override-Base-Url` header (Option 3) is required for correct Docker registry URL generation in Artifactory responses.
NGINX Ingress Migration – Configuration Comparison
Aspect
Deprecated ingress-nginx
NGINX Ingress Controller
Change
Ingress class
className: "nginx"
className: "nginx"
No change
Body size limit
nginx.ingress.kubernetes.io/proxy-body-size: "0"
nginx.org/client-max-body-size: "0"
Annotation key updated
Read timeout
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
nginx.org/proxy-read-timeout: "600"
Annotation key updated
Send timeout
nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
nginx.org/proxy-send-timeout: "600"
Annotation key updated
Custom rewrites
nginx.ingress.kubernetes.io/configuration-snippet
nginx.org/location-snippets
Annotation key updated
Docker v2 routing
Supported via rewrite rules
Supported via rewrite rules
No functional change
TLS configuration
Standard Kubernetes TLS secret
Standard Kubernetes TLS secret
No change
Artifactory paths
/ and /artifactory/
/ and /artifactory/
No change
Docker subdomain access
Via server-alias regex annotation
Via nginx.org/server-snippets + nginx.org/location-snippets
Annotation approach updated

Conclusion
NGINX Ingress Controller works as a supported replacement for the deprecated ingress-nginx setup and has been validated with Artifactory for TLS, non-TLS, and Docker subdomain configurations. The migration requires only ingress annotation key changes, with no functional impact on routing or behavior, and no changes to the JFrog installation or deployment process are needed. For Docker subdomain access, additional wildcard DNS and TLS prerequisites apply.