Apache Tika Server
Overview
Apache Tika Server is the standalone HTTP interface to the Apache Tika toolkit. Send it a PDF, Office file, email, image or any of more than a thousand supported formats. It returns the plain text content and structured metadata, such as author, title, dates and the detected media type.
Tika Server is stateless and holds no data between requests. That makes it a natural building block for search indexing, document processing and retrieval-augmented generation (RAG) pipelines that turn arbitrary files into clean, machine-readable text. It uses the mature Apache PDFBox and Apache POI parsers, so it copes with the variety of real-world documents.
Secure by default, no default login: Tika Server ships with no authentication, and its file-fetching and unpack features are a known SSRF/RCE risk if the port is exposed. This image never exposes it. The Tika server binds to loopback only, and the dangerous features stay disabled (the server is not started with -enableUnsecureFeatures). nginx is the only public listener and fronts the whole REST surface with HTTP Basic Auth.
On each VM's first boot, a tika-firstboot.service oneshot generates a unique password, writes a bcrypt .htpasswd and a root-only info note, and proves the auth gate with a real extraction round trip. It then disables itself. No two VMs share a password, and none is baked into the image.
Note on the interface: Tika Server is an API-first service with no bundled web interface. You drive it through its REST API, the official Tika client libraries or your own application. This guide uses curl against the API.
What you get:
- Apache Tika Server 3.3.1 (
tika-server-standard) on OpenJDK 17, with the official JAR installed at /opt/tika tika.servicebound to127.0.0.1:9998, run as a dedicated non-roottikauser under a hardened systemd unit- nginx reverse proxy on port 80 with per-VM HTTP Basic Auth, ready for TLS
- An unauthenticated
/healthzendpoint for load balancer and probe checks tika-firstboot.servicefor the per-VM first-boot password and gate proof- A unique per-VM password generated on first boot, in a root-only
0600file - Sample fixtures under
/opt/tika/samplesso you can test extraction immediately - Ubuntu 24.04 LTS base, patched at build time
- 24/7 SecureAnyCloud support with a 24-hour response SLA
Prerequisites
You need an active Azure subscription, an SSH key pair, and a VNet with a subnet. Tika is CPU- and memory-bound while parsing, so extracting large or complex documents benefits from more RAM.
The recommended VM size is Standard_B2s (2 vCPU, 4 GB RAM) for evaluation and light workloads. Use Standard_D2s_v5 or larger for production throughput and large documents.
Deploy from the Azure Portal
Search the Marketplace for Apache Tika Server on Ubuntu 24.04 and choose your VM size. Attach an NSG that allows TCP 22 (SSH) from your management network. Also allow TCP 80 and 443 (the API) from the networks and applications that submit documents.
In production, front port 80 with TLS (see the HTTPS step below).
Deploy from the Azure CLI
RG="tika-prod"; LOCATION="eastus"; VM_NAME="tika-01" IMAGE_URN="sac1647283583153:apache-tika-server-ubuntu-24-04:default:latest" SSH_KEY="$(cat ~/.ssh/id_rsa.pub)" az group create --name "$RG" --location "$LOCATION" az network vnet create -g "$RG" --name tika-vnet --address-prefix 10.90.0.0/16 --subnet-name tika-subnet --subnet-prefix 10.90.1.0/24 az network nsg create -g "$RG" --name tika-nsg az network nsg rule create -g "$RG" --nsg-name tika-nsg --name allow-ssh --priority 100 \
--source-address-prefixes "<your-mgmt-cidr>" --destination-port-ranges 22 --access Allow --protocol Tcp az network nsg rule create -g "$RG" --nsg-name tika-nsg --name allow-web --priority 110 \
--source-address-prefixes "<your-mgmt-cidr>" --destination-port-ranges 80 443 --access Allow --protocol Tcp
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:apache-tika-server-ubuntu-24-04:default:latest
az vm create -g "$RG" --name "$VM_NAME" --image "$IMAGE_URN" \
--size Standard_B2s --storage-sku StandardSSD_LRS \
--admin-username azureuser --ssh-key-values "$SSH_KEY" \
--vnet-name tika-vnet --subnet tika-subnet --nsg tika-nsg --public-ip-sku StandardConnect over SSH
ssh azureuser@<vm-ip>Verify the services are running
The Tika server listens on loopback 127.0.0.1:9998 and nginx fronts the API on port 80. The /healthz endpoint is public. Every other endpoint requires your per-VM password.
sudo systemctl is-active tika nginx
sudo ss -tln | grep -E ':80 |:9998' curl -s http://127.0.0.1/healthzYou should see both services active, the two listening sockets, and ok from the health endpoint.
Read your per-VM password
The password was generated on this VM's first boot and stored in a root-only file. Read it and keep it secret, because it authenticates every API request. Then confirm that unauthenticated requests are rejected.
sudo ls -l /root/tika-server-credentials.txt echo "unauthenticated /version -> HTTP $(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1/version)"The info note holds TIKA_USERNAME (admin) and TIKA_PASSWORD. It is owned by root:root with mode 0600. An unauthenticated call to /version returns 401, because the nginx Basic Auth gate enforces authentication.
Extract text from a document
This is what Tika does: it turns a document into plain text. Load the per-VM password into a shell variable, then submit a file to the /tika endpoint with a PUT.
The image ships sample PDF and DOCX fixtures under /opt/tika/samples so you can test immediately. Swap in your own files the same way.
export
TIKA_PW=$(sudo grep '^TIKA_PASSWORD=' /root/tika-server-credentials.txt | cut -d= -f2-)
# Extract text from the sample PDF curl -s -u "admin:$TIKA_PW" -T /opt/tika/samples/sac-sample.pdf \
-H 'Accept: text/plain' http://127.0.0.1/tika
# Extract text from the sample DOCX (any Office format works the same way)
curl -s -u "admin:$TIKA_PW" -T /opt/tika/samples/sac-sample.docx \
-H 'Accept: text/plain' http://127.0.0.1/tikaEach call returns the extracted plain text of the document. To extract from your own file, replace the path after -T with your document. Tika detects the type automatically.
Extract metadata
The /meta endpoint returns only the document metadata as JSON, such as detected content type, page or word counts, author and dates. The /rmeta endpoint returns a recursive JSON array that combines metadata and text for every embedded part of a container document.
export
TIKA_PW=$(sudo grep '^TIKA_PASSWORD=' /root/tika-server-credentials.txt | cut -d= -f2-)
# Metadata only, as JSON curl -s -u "admin:$TIKA_PW" -T /opt/tika/samples/sac-sample.docx \
-H 'Accept: application/json' http://127.0.0.1/meta echo
# Detect the media type of a file without parsing it curl -s -u "admin:$TIKA_PW" -T /opt/tika/samples/sac-sample.pdf \
http://127.0.0.1/detect/stream/meta reports fields such as Content-Type. /detect/stream returns the detected MIME type (application/pdf) using Tika's content detection, without a full parse.
Supported formats and endpoints
Tika parses over a thousand formats through a single API. The useful endpoints are listed below. All of them sit behind the Basic Auth gate.
PUT /tika: extract plain text (or XHTML withAccept: text/html)PUT /meta: extract metadata as JSON, CSV or XMPPUT /rmeta: recursive metadata and text for container formats (zip, mbox, PDF portfolios)PUT /detect/stream: detect the media type without parsingGET /version,GET /parsers,GET /detectors,GET /mime-types: introspect the server
List the parsers and detected MIME types the server supports:
export
TIKA_PW=$(sudo grep '^TIKA_PASSWORD=' /root/tika-server-credentials.txt | cut -d= -f2-)
curl -s -u "admin:$TIKA_PW" http://127.0.0.1/version
curl -s -u "admin:$TIKA_PW" http://127.0.0.1/detectors | head -20Enable HTTPS
nginx fronts the API on port 80 and is ready for TLS. Point a DNS record at the VM. Then obtain a certificate with certbot and let it configure nginx for port 443.
sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.example.comAfter issuance, restrict the NSG so that only port 443 (and port 22 from your management network) is reachable. Then submit documents over https://your-domain.example.com/tika.
Persistence, first boot and updates
Tika Server is stateless. It keeps no data between requests, so there is no data volume to manage. The Tika JAR and sample fixtures live on the OS disk and are captured into the image, so a VM launched from this image is ready immediately.
The first-boot service generates the per-VM Basic Auth password and proves the auth gate. It then disables itself, so later reboots are unaffected. The OS is patched at build time and ships with unattended security upgrades enabled.
To change the password later, edit /etc/nginx/.tika.htpasswd with sudo htpasswd -B /etc/nginx/.tika.htpasswd admin and reload nginx.
Support
Every SecureAnyCloud deployment includes 24/7 support with a 24-hour response SLA. Contact sales@secureanycloud.com for help with deployment, configuration or scaling.
This is a repackaged open source software product with additional charges for SecureAnyCloud support services. Apache Tika is a trademark of the Apache Software Foundation. All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.
Deploy on Azure
Launch Apache Tika Server on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com
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 through one consistent REST API. These include PDF, Microsoft Office and OpenDocument, HTML, RTF, EPUB, images, email and archive formats.
Tika Server has no built-in authentication and a real history of parser vulnerabilities, so an exposed, unauthenticated instance is a serious risk. This image is locked down by default.
What you get:
- Tika as a Java service on OpenJDK 17, running under a dedicated unprivileged
tikasystem account and managed by a hardened systemd unit that starts it on boot - A stateless service: each request turns an uploaded document into clean text or structured metadata and keeps no state, so there is no database and no data volume to manage
- A Tika listener on port 9998 bound to the loopback interface only, never reachable from the network
- nginx in front, terminating TLS on port 443 with a certificate generated uniquely on each instance, and enforcing HTTP Basic Auth with a password generated on first boot
- The dangerous URL-fetching and unpack features left disabled, which closes the classic server-side request forgery path to the instance metadata service
- IMDSv2 enforced, plus heap, systemd memory and upload-size limits that 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 options 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 that allows 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. You reach the service through the SSH tunnel described later, or through a 443 rule scoped to your own network.
Launch from the AWS Marketplace
- Open the product page in AWS Marketplace and choose Continue to Subscribe.
- Accept the terms, then choose Continue to Configuration.
- Select the software version and the Region you want to deploy into, then choose Continue to Launch.
- Choose Launch through EC2 for full control of networking and storage.
- Pick an instance type.
m5.largeis the recommended minimum. Scale up as your document sizes and request concurrency grow, because Tika is a JVM service and benefits from additional memory. - Select your VPC, subnet and key pair.
- Attach a security group that allows inbound TCP 22 from your management network. Do not add a rule for 9998.
- Launch, and wait for the instance to reach the 2/2 checks passed state.
Launch 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.serviceactive activeConfirm that the open 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/healthzokRetrieve 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.txtThe file contains the generated password, 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 instead of 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"; fiAPI password loaded (24 characters)Confirm the file is readable only by root:
sudo stat -c '%a %U:%G' /root/tika-server-credentials.txt600 root:rootExtract text and metadata
nginx serves the API 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. Alternatively, install your own certificate, as described later.
All of the following commands run on the instance against the loopback address. From your workstation, 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/versionApache Tika 3.3.1The 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/sac-sample.docx -H 'Accept: text/plain' https://127.0.0.1/tikaSacTikaProbe Apache Tika on sac 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/sac-sample.pdf -H 'Accept: text/plain' https://127.0.0.1/tikaSacTikaProbe Apache Tika on sac 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/sac-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. It 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/sac-sample.pdf -H 'Accept: application/json' https://127.0.0.1/rmeta | head -c 300; echoTo 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.
Security model
Two properties make this image safe to run. First, the API refuses any unauthenticated request, so 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. The following 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 leakIf the first line ever reads ALLOWED or the second reads LEAKED, do not use the instance and contact SecureAnyCloud support.
The Tika listener itself is bound to loopback only. You can confirm this: it appears against 127.0.0.1:9998, never against a public address:
sudo ss -tlnp | grep 9998LISTEN 0 50 127.0.0.1:9998 0.0.0.0:* users:(("java",...))Reach 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. The tunnel forwards your local port 8443 to the instance's nginx over the encrypted SSH connection, and exposes nothing extra 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/tikaExpose port 443 to your own network
To call the service directly instead of through a tunnel, add an inbound rule for TCP 443 scoped to your own network. Never use 0.0.0.0/0. The API requires a password, but 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.
Install 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.crtand/etc/nginx/tls/tika.keywith your certificate and private key (keep the key mode0640, ownerroot:www-data), then runsudo 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 that 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 -5Restart Tika after a configuration change, for example after editing the JVM heap in /etc/default/tika:
sudo systemctl restart tika.serviceThe 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. If your documents are large and you have provisioned more memory, raise both together. nginx caps a single upload at 128 MB (client_max_body_size). To process larger files, increase it in /etc/nginx/sites-available/sac-tika.
Support
Every SecureAnyCloud deployment is backed by 24/7 support from SecureAnyCloud engineers, by email at sales@secureanycloud.com 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, and wiring Tika into a search or retrieval-augmented-generation pipeline. It also covers TLS certificate and reverse-proxy configuration, credential management, and Tika upgrades and troubleshooting.
Deploy on AWS
Launch Apache Tika Server on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com