Applications AWS

Apache Tika Server on AWS User Guide

| Product: Apache Tika Server on AWS

Overview

This image runs Apache Tika Server 3.3.1, the Apache Software Foundation's content detection and extraction service. Tika detects and extracts text and metadata from thousands of file types - PDF, Microsoft Office and OpenDocument, HTML, RTF, EPUB, images, email and archive formats - through one consistent REST API.

Tika runs as a Java service on OpenJDK 17, under a dedicated unprivileged tika system account, managed by a hardened systemd unit that starts it on boot. It is a stateless service: each request turns an uploaded document into clean text or structured metadata and keeps no state between requests, so there is no database and no data volume to manage.

The Tika listener on port 9998 is bound to the loopback interface only and is never reachable from the network. In front of it, nginx terminates TLS on port 443 with a certificate generated uniquely on each instance, and enforces HTTP Basic Auth with a password generated on first boot. This is a deliberate default: Tika Server has no built-in authentication and a real history of parser vulnerabilities, so an exposed, unauthenticated Tika is a serious risk. The dangerous URL-fetching and unpack features are left disabled, closing the classic server-side request forgery path to the instance metadata service, IMDSv2 is enforced, and heap, systemd memory and upload-size limits contain a malicious oversized or zip-bomb upload.

The shipped security group opens only port 22. You reach the service over an SSH tunnel, or by adding a port 443 rule scoped to your own network. Both are covered below.

Prerequisites

Before you deploy this image you need:

  • An Amazon Web Services account where you can launch EC2 instances
  • IAM permissions to launch instances, create security groups, and subscribe to AWS Marketplace products
  • An EC2 key pair in the target Region for SSH access to the instance
  • A VPC and subnet in the target Region, with a security group allowing inbound port 22 from your management network only
  • An SSH client on your workstation, and curl (or any HTTP client) to call the API

You do not need to open port 9998, and you do not need to open port 443 to deploy. The service is reached through the SSH tunnel described later, or through a 443 rule scoped to your own network.

Launching from the AWS Marketplace

  1. Open the product page in AWS Marketplace and choose Continue to Subscribe
  2. Accept the terms, then choose Continue to Configuration
  3. Select the software version and the Region you want to deploy into, then choose Continue to Launch
  4. Choose Launch through EC2 for full control of networking and storage
  5. Pick an instance type. m5.large is the recommended minimum; scale up as your document sizes and request concurrency grow, since Tika is a JVM service and benefits from additional memory
  6. Select your VPC, subnet and key pair
  7. Attach a security group that allows inbound TCP 22 from your management network. Do not add a rule for 9998
  8. Launch, and wait for the instance to reach the 2/2 checks passed state

Launching with the AWS CLI

Substitute your own AMI id, key pair, security group and subnet:

aws ec2 run-instances \
  --image-id <ami-id> \
  --instance-type m5.large \
  --key-name <your-key-pair> \
  --security-group-ids <your-sg-id> \
  --subnet-id <your-subnet-id> \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=apache-tika}]'

Connecting to your instance

Connect over SSH as the default login user for your operating system variant. The image opens only port 22.

Variant SSH login user
Ubuntu 24.04 LTS ubuntu
ssh -i /path/to/your-key.pem ubuntu@<public-ip>

Confirm the two services are running:

systemctl is-active tika.service nginx.service
active
active

Confirm the open, unauthenticated health endpoint answers on port 80 (this is the only endpoint that does not require a password, and it is intended for load-balancer and probe checks):

curl -s http://127.0.0.1/healthz
ok

Retrieving the API credentials

The per instance HTTP Basic Auth password is written to a root-only file on first boot:

sudo cat /root/tika-server-credentials.txt

The file contains the generated password along with the API URL and worked curl examples:

# Apache Tika Server - generated on first boot by tika-firstboot.service
# These credentials are unique to this instance. Store them somewhere safe.

TIKA_URL=https://<this-instance-public-ip>/
TIKA_USERNAME=admin
TIKA_PASSWORD=<generated-on-first-boot>

Load the password into a shell variable rather than printing it, so it never lands in your shell history or terminal scrollback. The commands in the rest of this guide use $PW:

PW=$(sudo grep '^TIKA_PASSWORD=' /root/tika-server-credentials.txt | cut -d= -f2-)
if [ -n "$PW" ]; then echo "API password loaded (${#PW} characters)"; else echo "not yet generated"; fi
API password loaded (24 characters)

Confirm the file is readable only by root:

sudo stat -c '%a %U:%G' /root/tika-server-credentials.txt
600 root:root

Extracting text and metadata

The API is served by nginx over TLS on port 443, behind HTTP Basic Auth as user admin. The certificate is a per-instance self-signed certificate, so curl needs -k (or install your own certificate, covered later). All of the following commands run on the instance against the loopback address; from your workstation you would use the tunnel or a scoped 443 rule described below.

Confirm the server version through the authenticated endpoint:

PW=$(sudo grep '^TIKA_PASSWORD=' /root/tika-server-credentials.txt | cut -d= -f2-)
curl -sk -u "admin:$PW" https://127.0.0.1/version
Apache Tika 3.3.1

The image ships two sample documents so you can prove a real extraction round trip immediately. Extract plain text from the sample DOCX with a PUT to /tika:

PW=$(sudo grep '^TIKA_PASSWORD=' /root/tika-server-credentials.txt | cut -d= -f2-)
curl -sk -u "admin:$PW" -T /opt/tika/samples/cloudimg-sample.docx -H 'Accept: text/plain' https://127.0.0.1/tika
CloudimgTikaProbe Apache Tika on cloudimg extracts text and metadata from this document.

Extraction from a PDF works the same way - Tika detects the type from the content, not the file name:

PW=$(sudo grep '^TIKA_PASSWORD=' /root/tika-server-credentials.txt | cut -d= -f2-)
curl -sk -u "admin:$PW" -T /opt/tika/samples/cloudimg-sample.pdf -H 'Accept: text/plain' https://127.0.0.1/tika
CloudimgTikaProbe Apache Tika on cloudimg extracts text and metadata from this document.

Ask for metadata as JSON with a PUT to /meta. Tika returns the detected content type and every metadata field it can read from the document:

PW=$(sudo grep '^TIKA_PASSWORD=' /root/tika-server-credentials.txt | cut -d= -f2-)
curl -sk -u "admin:$PW" -T /opt/tika/samples/cloudimg-sample.docx -H 'Accept: application/json' https://127.0.0.1/meta | head -c 400; echo
{"Content-Length":"...","Content-Type":"application/vnd.openxmlformats-officedocument.wordprocessingml.document", ...}

To extract text and metadata together, including from container formats such as ZIP archives and email, use the recursive endpoint /rmeta, which returns a JSON array with one object per embedded document:

PW=$(sudo grep '^TIKA_PASSWORD=' /root/tika-server-credentials.txt | cut -d= -f2-)
curl -sk -u "admin:$PW" -T /opt/tika/samples/cloudimg-sample.pdf -H 'Accept: application/json' https://127.0.0.1/rmeta | head -c 300; echo

To extract from your own file, replace the path after -T with your document. The Accept header selects the output: text/plain for text, application/json for metadata.

The security model

Two properties make this image safe to run. First, the API refuses any unauthenticated request - there is no anonymous access to extraction. Second, the URL-fetching feature that has historically enabled server-side request forgery against the instance metadata service is disabled, so a request that tries to make Tika fetch a URL leaks nothing. This check proves both, without printing the password:

PW=$(sudo grep '^TIKA_PASSWORD=' /root/tika-server-credentials.txt | cut -d= -f2-)
UNAUTH=$(curl -sk -o /dev/null -w '%{http_code}' https://127.0.0.1/version)
[ "$UNAUTH" = 401 ] && echo "unauthenticated request: REJECTED (401)" || echo "unauthenticated request: ALLOWED ($UNAUTH)"
SSRF=$(curl -sk -u "admin:$PW" -H 'fileUrl: http://169.254.169.254/latest/meta-data/iam/security-credentials/' -H 'Accept: text/plain' https://127.0.0.1/tika)
echo "$SSRF" | grep -qiE 'AccessKeyId|InstanceProfileArn|iam/security-credentials' && echo "metadata SSRF: LEAKED" || echo "metadata SSRF: no leak"
unauthenticated request: REJECTED (401)
metadata SSRF: no leak

If the first line ever reads ALLOWED or the second reads LEAKED, do not use the instance and contact cloudimg support.

The Tika listener itself is bound to loopback only, which you can confirm - it appears against 127.0.0.1:9998, never against a public address:

sudo ss -tlnp | grep 9998
LISTEN 0 50 127.0.0.1:9998 0.0.0.0:* users:(("java",...))

Reaching the service from your workstation

The security group opens only port 22, so the simplest and safest way to reach the API from your workstation is an SSH tunnel. This forwards your local port 8443 to the instance's nginx over the encrypted SSH connection, with nothing extra exposed to the network:

ssh -i /path/to/your-key.pem -L 8443:127.0.0.1:443 ubuntu@<public-ip>

With the tunnel open, call the API from your workstation against https://127.0.0.1:8443 using the password from the credentials file (again -k, for the self-signed certificate):

curl -k -u admin:<password> -T report.pdf -H 'Accept: text/plain' https://127.0.0.1:8443/tika

Exposing port 443 to your own network

If you prefer to call the service directly rather than through a tunnel, add an inbound rule for TCP 443 scoped to your own network - never 0.0.0.0/0, because although the API requires a password, narrowing the source is basic hygiene:

aws ec2 authorize-security-group-ingress \
  --group-id <your-sg-id> \
  --protocol tcp --port 443 \
  --cidr <your-mgmt-cidr>

Then call https://<instance-public-ip>/tika from within that network.

Installing your own TLS certificate

The image generates a per-instance self-signed certificate so the API is encrypted from first boot. For production you will usually front the instance with your own certificate or an upstream load balancer:

  • Your own certificate: replace /etc/nginx/tls/tika.crt and /etc/nginx/tls/tika.key with your certificate and private key (keep the key mode 0640, owner root:www-data), then sudo systemctl reload nginx. Clients no longer need -k.
  • Upstream load balancer: terminate TLS at an Application Load Balancer or a proxy in front of the instance and forward to port 443 (or reconfigure nginx to listen on 80 behind the load balancer). Scope the security group so only the load balancer reaches the instance.

Endpoint reference

All endpoints except /healthz require HTTP Basic Auth over TLS.

Method Path Purpose
PUT /tika Extract plain text (or XHTML) from the uploaded document
PUT /meta Extract document metadata as JSON
PUT /rmeta Recursive text and metadata for container formats, as a JSON array
GET /version Server version string
GET /detectors The content detectors Tika will use
GET /parsers The parsers Tika will use
GET /healthz Open, unauthenticated health check on port 80 (returns ok)

Managing the service

Tika and nginx are ordinary systemd services:

systemctl status tika.service --no-pager | head -5

Restart Tika after a configuration change (for example after editing the JVM heap in /etc/default/tika):

sudo systemctl restart tika.service

The JVM heap is capped in /etc/default/tika (-Xmx1024m by default) and the systemd unit sets MemoryMax=1536M, so a single very large or malicious upload cannot exhaust the instance. Raise both together if your documents are large and you have provisioned more memory. nginx caps a single upload at 128 MB (client_max_body_size); increase it in /etc/nginx/sites-available/cloudimg-tika if you need to process larger files.

Support

Every cloudimg deployment is backed by 24/7 support from cloudimg engineers by email at support@cloudimg.co.uk and by live chat, with a one-hour average response for critical issues. Support covers deployment and sizing, tuning the JVM heap and Tika configuration for your document mix, enabling OCR or additional parsers, wiring Tika into a search or retrieval-augmented-generation pipeline, TLS certificate and reverse-proxy configuration, credential management, and Tika upgrades and troubleshooting.