Skip to main content
Skip table of contents

Configure a Reverse Proxy in SignServer

It is best practice to place SignServer behind a reverse proxy server that handles TLS termination or load balancing for any production-like deployment. Configuring SignServer as a proxy back-end disables its internal TLS setup, which means the Admin UI will be open to anyone with network access unless the proxy enforces access controls.

When binding a proxy back-end protocol port, there are two approaches:

  • Binding to 0.0.0.0 exposes the port on all interfaces. Care must be taken to ensure no traffic can reach the bound port directly, bypassing the proxy.

  • Binding to 127.0.0.1 restricts access to the local loopback interface, which is the expected setup when using a sidecar container deployed in the same Kubernetes Pod to forward requests internally.

Option

Description

Use Case

Built-in NGINX Reverse Proxy

RECOMMENDED

Uses a Keyfactor-provided NGINX sidecar that is configured alongside SignServer in the same Helm deployment.

For integrated, low-overhead setup without managing a separate proxy.

External Reverse Proxy with AJP

Exposes SignServer through the AJP protocol on port 8009, to be used with an external reverse proxy (such as Apache HTTP Server) that speaks AJP.

If your existing infrastructure uses an AJP-compatible proxy, or if your organization's standards require AJP-based communication between the proxy and the application server.

External Reverse Proxy with HTTP Back-end Ports

Exposes SignServer over HTTP (port 8081) and HTTPS (port 8082) for use with any standard reverse proxy, such as NGINX or HAProxy, that you manage externally. Port 8082 supports the SSL_CLIENT_CERT header for mTLS pass-through.

If you already have an external reverse proxy in place and prefer HTTP-based communication over AJP.

TLS Termination in the Container

Skips the reverse proxy entirely. SignServer handles TLS itself using JKS keystores you provide as Kubernetes secrets.

If you are not using a reverse proxy at all, for example, in a development or test environment. Not recommended for production.

Option A: Built-in NGINX Reverse Proxy

To expose SignServer through an NGINX reverse proxy that handles TLS termination, enable the built-in NGINX reverse proxy and use the HTTP proxy back-end ports. Port 8082 accepts the SSL_CLIENT_CERT header for mTLS pass-through to SignServer.

Create the Kubernetes secret for secretInternalNginxCert, containing the NGINX server certificate, private key, and CA certificate used to verify client certificates. The file names must match the configured nginx.host, for example signserverhost.pem, signserverhost-Key.pem, and signserverhost-CA.pem.

Example secret creation:

CODE
kubectl create secret generic managementca-secret \
  --namespace default \
  --from-file=signserverhost.pem=/path/to/certificate.pem \
  --from-file=signserverhost-Key.pem=/path/to/key.pem \
  --from-file=signserverhost-CA.pem=/path/to/ca-certificate.pem

Configure the NGINX host. For more information on the parameters, see SignServer Helm Deployment Parameters | NGINX-Reverse-Proxy-Parameters:

YAML
nginx:
  image: nginx:1.27.1
  enabled: true
  initializeWithSelfSignedTls: false
  host: "signserverhost"
  externalConfiguration:
  # Server TLS credential for cluster internal communication
  mountInternalNginxCert: true
  secretInternalNginxCert: "managementca-secret"
  service:
    type: LoadBalancer
    bindIP: 0.0.0.0
    httpPort: 80
    httpsPort: 443
  # only relevant if multiple replicas
  loadBalancerAccess:
    enableStickySessionClientIp: false
    # create a load balancer service for each Pod with separate IP address
    enableReplicaSpecificAccess: false
  additionalHosts:

Create the NGINX reverse proxy:

YAML
services:
  directHttp:
    enabled: false
  proxyAJP:
    enabled: false
  proxyHttp:
    enabled: true
    type: ClusterIP
    bindIP: 0.0.0.0
    httpPort: 8081
    httpsPort: 8082

Option B: External Reverse Proxy with AJP

This option exposes SignServer through the AJP (Apache JServ Protocol) on port 8009 as a ClusterIP service. Your external reverse proxy connects to this port and handles TLS termination before forwarding requests.

In the Helm values, directHttp and proxyHttp are both disabled, and proxyAJP is enabled with bindIP: 0.0.0.0 and port: 8009. The AJP service is internal to the cluster ClusterIP, so the external proxy must be able to reach it within the cluster network:

YAML
services:
  directHttp:
    enabled: false
  proxyAJP:
    enabled: true
    type: ClusterIP
    bindIP: 0.0.0.0
    port: 8009
  proxyHttp:
    enabled: false

Option C: External Reverse Proxy with HTTP Back-end Ports

This option is similar to the built-in NGINX in terms of the ports used, but instead of using the built-in NGINX sidecar, you connect your own externally managed reverse proxy to SignServer's HTTP back-end ports. Port 8081 handles plain HTTP traffic, and port 8082 handles HTTPS and accepts the SSL_CLIENT_CERT header, enabling mTLS pass-through so that client certificate information is forwarded to SignServer.

In the Helm values, directHttp and proxyAJP are disabled, and proxyHttp is enabled with ClusterIP type, binding to 0.0.0.0 on ports 8081 and 8082.

YAML
services:
  directHttp:
    enabled: false
  proxyAJP:
    enabled: false
  proxyHttp:
    enabled: true
    type: ClusterIP
    bindIP: 0.0.0.0
    httpPort: 8081
    httpsPort: 8082

Option D: TLS Termination Directly in the Container

If you are not using a reverse proxy, SignServer handles TLS itself using JKS (Java KeyStore) keystores that you supply as Kubernetes secrets. Two secrets are required:

  • A keystore secret containing server.jks (the server TLS keystore) and server.storepasswd (a file with the keystore password)

  • A truststore secret containing truststore.jks (the mTLS truststore with the CA certificate(s) that issue administrator client certificates) and truststore.storepasswd

CODE
kubectl create secret generic keystore-secret \
    --from-file=server.jks=server.jks \
    --from-file=server.storepasswd=server.storepasswd
kubectl create secret generic truststore-secret \
    --from-file=truststore.jks=ManagementCA-chain.jks \
    --from-file=truststore.storepasswd=truststore.storepasswd

Once the secrets are created, configure the Helm chart to import the secrets using importAppserverKeystore: true and importAppserverTruststore: true, pointing to the respective secret names:

YAML
signserver:
  importAppserverKeystore: true
  appserverKeystoreSecret: keystore-secret
  importAppserverTruststore: true
  appserverTruststoreSecret: truststore-secret
JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.