TLS/SSL Configuration

Tika Server supports TLS (Transport Layer Security) for encrypted communication and mutual authentication (2-way TLS / mTLS).

Choosing a Security Approach

For most deployments, we recommend placing Tika Server behind a reverse proxy (such as nginx, Apache httpd, or Traefik) that handles TLS termination. This approach simplifies certificate management, enables additional features like rate limiting and authentication, and follows a well-established pattern with extensive documentation. In this setup, the reverse proxy handles HTTPS connections from clients, and Tika Server runs on plain HTTP in a private network or on localhost. If you need token-based authentication (JWT, API keys, OAuth2), an API gateway or reverse proxy with authentication modules is the recommended approach, as Tika Server does not include built-in token support.

Direct TLS configuration on Tika Server (described in this document) is useful when you cannot use a reverse proxy, need client certificate authentication (2-way TLS/mTLS), or prefer a simpler single-process deployment. If you only need to restrict access without TLS, consider network-level controls such as binding to localhost, firewall rules, or running in a private subnet.

Overview

TLS configuration options:

  • 1-Way TLS: Server presents its certificate; clients verify the server

  • 2-Way TLS (mTLS): Both server and client present certificates for mutual authentication

Quick Start

1-Way TLS

Server authenticates to clients, but clients are not required to present certificates.

{
  "server": {
    "host": "localhost",
    "port": 9998
  },
  "tlsConfig": {
    "active": true,
    "keyStoreType": "PKCS12",
    "keyStoreFile": "/path/to/server-keystore.p12",
    "keyStorePassword": "your-password",
    "clientAuthenticationWanted": false,
    "clientAuthenticationRequired": false
  }
}

2-Way TLS (mTLS)

Both server and client must present valid certificates.

{
  "server": {
    "host": "localhost",
    "port": 9998
  },
  "tlsConfig": {
    "active": true,
    "keyStoreType": "PKCS12",
    "keyStoreFile": "/path/to/server-keystore.p12",
    "keyStorePassword": "your-password",
    "trustStoreType": "PKCS12",
    "trustStoreFile": "/path/to/server-truststore.p12",
    "trustStorePassword": "your-password",
    "clientAuthenticationWanted": true,
    "clientAuthenticationRequired": true
  }
}

Docker Deployment

When running Tika Server in Docker with TLS, you need to:

  1. Create a configuration file with TLS settings

  2. Mount the configuration file into the container

  3. Mount the keystore (and truststore for 2-way TLS) into the container

  4. Start the container with the -c flag pointing to the config file

Directory Structure

Create a directory structure on your host machine:

tika-tls/
├── config/
│   └── tika-config.json
└── certs/
    ├── server-keystore.p12
    └── server-truststore.p12    # (for 2-way TLS)

Configuration File

Create tika-tls/config/tika-config.json:

{
  "server": {
    "host": "0.0.0.0",
    "port": 9998
  },
  "tlsConfig": {
    "active": true,
    "keyStoreType": "PKCS12",
    "keyStoreFile": "/tika/certs/server-keystore.p12",
    "keyStorePassword": "your-password",
    "trustStoreType": "PKCS12",
    "trustStoreFile": "/tika/certs/server-truststore.p12",
    "trustStorePassword": "your-password",
    "clientAuthenticationRequired": true
  }
}
Use 0.0.0.0 as the host to bind to all interfaces inside the container. The paths (/tika/certs/…​) must match where you mount the files in the container.

Running with Docker

docker run -d \
  --name tika-server \
  -p 9998:9998 \
  -v $(pwd)/tika-tls/config:/tika/config:ro \
  -v $(pwd)/tika-tls/certs:/tika/certs:ro \
  apache/tika:<version> \
  -c /tika/config/tika-config.json

Options explained:

  • -p 9998:9998 - Expose the HTTPS port

  • -v …​/config:/tika/config:ro - Mount config directory (read-only)

  • -v …​/certs:/tika/certs:ro - Mount certificates directory (read-only)

  • -c /tika/config/tika-config.json - Path to config file inside container

Docker Compose

For more complex deployments, use Docker Compose:

# docker-compose.yml
version: '3.8'

services:
  tika:
    image: apache/tika:latest
    ports:
      - "9998:9998"
    volumes:
      - ./config:/tika/config:ro
      - ./certs:/tika/certs:ro
    command: ["-c", "/tika/config/tika-config.json"]
    healthcheck:
      test: ["CMD", "curl", "-f", "--cacert", "/tika/certs/server.crt", "https://localhost:9998/tika"]
      interval: 30s
      timeout: 10s
      retries: 3

Run with:

docker-compose up -d

Using Secrets (Docker Swarm / Kubernetes)

For production deployments, avoid storing passwords in plain text config files.

Docker Swarm

Use Docker secrets for sensitive data:

# Create secrets
echo "your-keystore-password" | docker secret create tika_keystore_password -
echo "your-truststore-password" | docker secret create tika_truststore_password -

# Reference in docker-compose.yml (swarm mode)
services:
  tika:
    image: apache/tika:latest
    secrets:
      - tika_keystore_password
      - tika_truststore_password
    # Read password from /run/secrets/tika_keystore_password in entrypoint script

Kubernetes

Use Kubernetes secrets:

# Create secret for certificates
kubectl create secret generic tika-tls-certs \
  --from-file=server-keystore.p12=./certs/server-keystore.p12 \
  --from-file=server-truststore.p12=./certs/server-truststore.p12

# Create secret for passwords
kubectl create secret generic tika-tls-passwords \
  --from-literal=keystore-password=your-password \
  --from-literal=truststore-password=your-password
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: tika-server
spec:
  replicas: 1
  selector:
    matchLabels:
      app: tika
  template:
    metadata:
      labels:
        app: tika
    spec:
      containers:
      - name: tika
        image: apache/tika:latest
        ports:
        - containerPort: 9998
        args: ["-c", "/tika/config/tika-config.json"]
        volumeMounts:
        - name: config
          mountPath: /tika/config
          readOnly: true
        - name: certs
          mountPath: /tika/certs
          readOnly: true
        env:
        - name: KEYSTORE_PASSWORD
          valueFrom:
            secretKeyRef:
              name: tika-tls-passwords
              key: keystore-password
      volumes:
      - name: config
        configMap:
          name: tika-config
      - name: certs
        secret:
          secretName: tika-tls-certs

Testing Docker TLS Setup

Test that TLS is working:

# 1-way TLS (trust server certificate)
curl --cacert ./certs/server.crt https://localhost:9998/tika

# 2-way TLS (provide client certificate)
curl --cacert ./certs/server.crt \
     --cert ./certs/client.crt \
     --key ./certs/client-key.pem \
     https://localhost:9998/tika

If using self-signed certificates and just testing:

# Skip certificate verification (NOT for production!)
curl -k https://localhost:9998/tika

Configuration Reference

tlsConfig Properties

Property Type Default Description

active

boolean

false

Enable TLS. When true, the server uses HTTPS.

keyStoreType

string

null

Keystore format: PKCS12 (recommended) or JKS.

keyStoreFile

string

null

Path to the server’s keystore file containing its private key and certificate.

keyStorePassword

string

null

Password for the keystore.

trustStoreType

string

null

Truststore format: PKCS12 (recommended) or JKS.

trustStoreFile

string

null

Path to the truststore containing trusted client certificates (for 2-way TLS).

trustStorePassword

string

null

Password for the truststore.

clientAuthenticationWanted

boolean

false

Request client certificates but don’t require them. Clients without certificates can still connect.

clientAuthenticationRequired

boolean

false

Require client certificates. Clients must present a valid certificate trusted by the server.

includedProtocols

list

["TLSv1.2", "TLSv1.3"]

TLS protocol versions to enable. Default only allows TLS 1.2 and 1.3.

excludedProtocols

list

null

TLS protocol versions to explicitly disable.

includedCipherSuites

list

null

Cipher suites to enable. If null, uses JVM defaults.

excludedCipherSuites

list

null

Cipher suites to disable.

certExpirationWarningDays

integer

30

Days before certificate expiration to log warnings. Set to 0 to disable.

Certificate Expiration Warnings

Tika Server automatically checks certificate expiration at startup and logs warnings for certificates that will expire soon. This helps prevent unexpected outages due to expired certificates.

Warning Levels

  • ERROR: Certificate has already expired or is not yet valid - TLS will fail

  • WARN: Certificate expires within the configured threshold (default: 30 days)

  • DEBUG: Certificate is valid (logged at debug level)

Example Log Output

WARN  TlsConfig - Certificate 'server' in keystore expires in 15 days on Sat Feb 15 12:00:00 UTC 2026. Consider renewing soon.
ERROR TlsConfig - Certificate 'server' in keystore has EXPIRED on Mon Jan 01 12:00:00 UTC 2026. TLS connections will fail!

Configuring the Warning Threshold

To change when warnings are logged (default is 30 days before expiration):

{
  "tlsConfig": {
    "active": true,
    "keyStoreType": "PKCS12",
    "keyStoreFile": "/path/to/server-keystore.p12",
    "keyStorePassword": "your-password",
    "certExpirationWarningDays": 60
  }
}

Set to 0 to disable expiration checking.

Generating Certificates

This section shows how to generate self-signed certificates for testing. For production, use certificates from a trusted Certificate Authority (CA).

Generate Server Keystore

# Generate server private key and certificate
keytool -genkeypair \
  -alias server \
  -keyalg RSA \
  -keysize 2048 \
  -validity 365 \
  -keystore server-keystore.p12 \
  -storetype PKCS12 \
  -storepass changeit \
  -dname "CN=localhost,OU=Tika,O=Apache,L=Unknown,ST=Unknown,C=US"

# Export server certificate (for clients to trust)
keytool -exportcert \
  -alias server \
  -keystore server-keystore.p12 \
  -storetype PKCS12 \
  -storepass changeit \
  -file server.crt

Generate Client Keystore (for 2-Way TLS)

# Generate client private key and certificate
keytool -genkeypair \
  -alias client \
  -keyalg RSA \
  -keysize 2048 \
  -validity 365 \
  -keystore client-keystore.p12 \
  -storetype PKCS12 \
  -storepass changeit \
  -dname "CN=TikaClient,OU=Tika,O=Apache,L=Unknown,ST=Unknown,C=US"

# Export client certificate (for server to trust)
keytool -exportcert \
  -alias client \
  -keystore client-keystore.p12 \
  -storetype PKCS12 \
  -storepass changeit \
  -file client.crt

Create Truststores

# Create server truststore (import client certificate)
keytool -importcert \
  -alias client \
  -file client.crt \
  -keystore server-truststore.p12 \
  -storetype PKCS12 \
  -storepass changeit \
  -noprompt

# Create client truststore (import server certificate)
keytool -importcert \
  -alias server \
  -file server.crt \
  -keystore client-truststore.p12 \
  -storetype PKCS12 \
  -storepass changeit \
  -noprompt

Protocol and Cipher Configuration

Restricting TLS Versions

By default, only TLS 1.2 and TLS 1.3 are enabled. TLS 1.0 and 1.1 are considered insecure and are not enabled by default.

To use only TLS 1.3:

{
  "tlsConfig": {
    "active": true,
    "keyStoreType": "PKCS12",
    "keyStoreFile": "/path/to/server-keystore.p12",
    "keyStorePassword": "your-password",
    "includedProtocols": ["TLSv1.3"]
  }
}

Restricting Cipher Suites

To allow only specific cipher suites:

{
  "tlsConfig": {
    "active": true,
    "keyStoreType": "PKCS12",
    "keyStoreFile": "/path/to/server-keystore.p12",
    "keyStorePassword": "your-password",
    "includedCipherSuites": [
      "TLS_AES_256_GCM_SHA384",
      "TLS_AES_128_GCM_SHA256",
      "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
      "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
    ]
  }
}

To exclude weak cipher suites:

{
  "tlsConfig": {
    "active": true,
    "keyStoreType": "PKCS12",
    "keyStoreFile": "/path/to/server-keystore.p12",
    "keyStorePassword": "your-password",
    "excludedCipherSuites": [
      ".*CBC.*",
      ".*RC4.*",
      ".*3DES.*",
      ".*NULL.*"
    ]
  }
}

Testing TLS Configuration

Test with curl (1-Way TLS)

# Trust the server certificate
curl --cacert server.crt https://localhost:9998/tika

Test with curl (2-Way TLS)

# Provide client certificate and trust server certificate
curl --cacert server.crt \
     --cert client.crt \
     --key client-key.pem \
     https://localhost:9998/tika

Test with Java Client

// Configure SSL context for 2-way TLS
SSLContext sslContext = SSLContexts.custom()
    .loadKeyMaterial(
        new File("client-keystore.p12"),
        "changeit".toCharArray(),
        "changeit".toCharArray())
    .loadTrustMaterial(
        new File("client-truststore.p12"),
        "changeit".toCharArray())
    .build();

HttpClient client = HttpClients.custom()
    .setSSLContext(sslContext)
    .build();

HttpGet request = new HttpGet("https://localhost:9998/tika");
HttpResponse response = client.execute(request);

Security Best Practices

  1. Use strong passwords for keystores and truststores

  2. Use TLS 1.2 or 1.3 only (default configuration)

  3. Prefer PKCS12 format over JKS (better interoperability)

  4. Use certificates from a trusted CA in production

  5. Rotate certificates before they expire

  6. Restrict cipher suites to strong, modern algorithms

  7. Use 2-way TLS when clients need to be authenticated

  8. Protect keystore files with appropriate file system permissions

  9. Never commit passwords to version control; use environment variables or secrets management

Troubleshooting

Common Errors

"keyStoreFile does not exist or is not a file"

The specified keystore file path is incorrect or the file doesn’t exist. Verify the path is absolute or relative to the working directory.

"Partial truststore configuration detected"

You’ve set some but not all truststore properties. Either set all three (trustStoreType, trustStoreFile, trustStorePassword) or none.

"requiring client authentication, but no trust store has been specified"

You’ve set clientAuthenticationRequired: true but haven’t configured a truststore. The server needs a truststore to verify client certificates.

SSL handshake failures

  • Verify certificates are valid and not expired

  • Ensure client trusts server certificate (for 1-way TLS)

  • Ensure server trusts client certificate (for 2-way TLS)

  • Check that protocol versions and cipher suites are compatible

Enable SSL Debug Logging

Add this JVM argument to see detailed SSL handshake information:

java -Djavax.net.debug=ssl:handshake -jar tika-server-standard.jar -c config.json

See Also

  • Security - General security considerations

  • Robustness - Process isolation and fault tolerance