Artificial Intelligence (AI) AWS

LanguageTool Grammar and Style API on AWS User Guide

| Product: LanguageTool Grammar and Style Checker

Overview

LanguageTool is an open source proofreading engine that checks grammar, style and spelling in dozens of languages. Send it a block of text and it returns a structured list of issues, each with the rule that fired, a human readable message, the offending span and suggested replacements. It combines a large library of hand written linguistic rules with statistical and machine learning models, and because it runs entirely inside your own account, the text you check never leaves your infrastructure. That makes it a natural building block for writing assistants, editors, content and documentation pipelines, and any application that wants proofreading without sending user text to a third party cloud service.

The cloudimg image installs the official LanguageTool 6.6 standalone distribution at /opt/languagetool, running as the languagetool service under OpenJDK 17 bound to loopback 127.0.0.1:8081, behind nginx on port 80. Only the open source LanguageTool core is shipped: the premium and paid features, the hosted LanguageTool cloud API, and the optional multi gigabyte n-gram datasets are not included.

Secure by default, no default login: the LanguageTool server ships with no authentication, and its /v2/check endpoint is CPU intensive and abusable if the port is exposed. This image never exposes it. The server binds loopback only (the public mode that opens it to the network requires an explicit flag that is never passed), and nginx is the only public listener, fronting the whole REST surface with HTTP Basic Auth. A languagetool-firstboot.service oneshot generates a unique per instance password on each instance's first boot, writes a bcrypt .htpasswd and a root only info note, proves the auth gate with a real grammar check round trip, then disables itself. No two instances share a password and none is baked into the image.

Note on the interface: LanguageTool Server is an API first service with no bundled web interface. You drive it through its REST API, the official LanguageTool clients and browser add ons (pointed at your server), or your own application. This guide uses curl against the API.

What is included:

  • LanguageTool 6.6 (languagetool-server) on OpenJDK 17
  • languagetool.service bound to 127.0.0.1:8081, run as a dedicated non root languagetool user under a hardened systemd unit
  • nginx reverse proxy on port 80 with per instance HTTP Basic Auth, ready for TLS
  • An unauthenticated /healthz endpoint for load balancer and probe checks
  • languagetool-firstboot.service for the first boot per instance password and gate proof
  • A unique per instance password generated on first boot, in a root only 0600 file
  • All base language models bundled in the distribution, so checking works immediately
  • Ubuntu 24.04 LTS base, fully patched
  • 24/7 cloudimg support

Connecting to your instance

Connect over SSH on port 22 as the default login user for your operating system variant. Replace <public-ip> with your instance's public IP or DNS name, and use the private key for the key pair you launched with.

OS variant Login user
Ubuntu 24.04 LTS ubuntu
ssh -i /path/to/key.pem ubuntu@<public-ip>

Prerequisites

An AWS account, an EC2 key pair, and a VPC with a subnet. LanguageTool is CPU and memory bound while checking; the JVM heap is sized for the recommended instance type. Recommended instance type: m5.large (2 vCPU, 8 GB RAM) for evaluation and light workloads, or a larger m5/c5 instance for production throughput and higher concurrency.

Step 1: Launch from the AWS Console

In the EC2 console choose Launch instance from AMI, select the cloudimg LanguageTool image, pick an m5.large (or larger) instance type, and attach a security group that allows TCP 22 (SSH) from your management network and TCP 80 (the API) from the networks and applications that need to submit text. Restrict port 80 to those clients; front it with TLS in production (see the HTTPS section below).

Step 2: Launch from the AWS CLI

aws ec2 run-instances \
  --image-id ami-xxxxxxxxxxxxxxxxx \
  --instance-type m5.large \
  --key-name my-key \
  --security-group-ids sg-xxxxxxxx \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=languagetool-01}]'

Step 3: Verify the services are running

Once connected over SSH, confirm both services are active.

systemctl is-active languagetool nginx

Both should report active. The LanguageTool server listens on loopback 127.0.0.1:8081; nginx is the public listener on port 80.

Step 4: Read your per instance password

The first boot service generated a unique HTTP Basic Auth password for this instance and wrote it to a root only file. Read it with:

sudo cat /root/languagetool-credentials.txt

The file records the API URL, the user name (admin) and the generated password. The examples below read the password straight from that file so it never appears on your screen.

Step 5: Check some text

Send a sentence with a deliberate agreement error to /v2/check. The JSON response lists each issue with its message and suggested replacements.

PW=$(sudo grep '^LT_PASSWORD=' /root/languagetool-credentials.txt | cut -d= -f2-)
curl -sS -u "admin:$PW" \
  --data-urlencode 'text=This are an test.' \
  --data-urlencode 'language=en-US' \
  http://localhost/v2/check \
  | python3 -c 'import json,sys; d=json.load(sys.stdin); s=d["software"]; print(s["name"], s["version"]); print(len(d["matches"]), "issue(s):"); [print("-", m["message"], "->", ", ".join(r["value"] for r in m["replacements"][:3])) for m in d["matches"]]'

You will see LanguageTool 6.6 flag the singular/plural disagreement (this ... are) and the article before test, each with suggested corrections.

Step 6: List the supported languages

PW=$(sudo grep '^LT_PASSWORD=' /root/languagetool-credentials.txt | cut -d= -f2-)
curl -sS -u "admin:$PW" http://localhost/v2/languages \
  | python3 -c 'import json,sys; d=json.load(sys.stdin); print(len(d), "languages"); [print("-", x["name"], x["longCode"]) for x in d[:12]]'

Step 7: Automatic language detection

Omit the language parameter and pass language=auto to let LanguageTool detect the language of the submitted text.

PW=$(sudo grep '^LT_PASSWORD=' /root/languagetool-credentials.txt | cut -d= -f2-)
curl -sS -u "admin:$PW" \
  --data-urlencode 'text=Ceci est un test' \
  --data-urlencode 'language=auto' \
  http://localhost/v2/check \
  | python3 -c 'import json,sys; d=json.load(sys.stdin); print("detected:", d.get("language",{}).get("detectedLanguage",{}).get("name"))'

Step 8: The open health endpoint

/healthz is unauthenticated and returns ok, for load balancer target checks and readiness probes.

curl -sS http://localhost/healthz

Step 9: Call the API from your workstation or application

From a client that can reach port 80, point at the instance's public IP or DNS name and authenticate with the admin user and the generated password. Restrict the security group so only your clients can reach port 80.

curl -u admin:<password> \
  --data-urlencode 'text=This are an test.' \
  --data-urlencode 'language=en-US' \
  http://<public-ip>/v2/check

The official LanguageTool browser add ons and editor plugins can also be pointed at http://<public-ip>/ (or your TLS endpoint) as a custom server.

Optional: add n-gram data for fewer false positives

The base language models are bundled, so checking works out of the box. LanguageTool can optionally load large n-gram datasets to reduce false positives on confused words. These datasets are several gigabytes per language and are not shipped in the image. To add them, download the dataset for your language from the LanguageTool project, extract it to a dedicated data disk, and set languageModel in /opt/languagetool/server.properties to its parent directory, then restart the service. See the LanguageTool documentation for details.

Enable HTTPS

Terminate TLS in front of nginx in production. Either place the instance behind an AWS Application Load Balancer with an ACM certificate and forward to port 80, or add a certificate directly to the nginx server block. A minimal in place approach uses certbot:

sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.example.com

Point your DNS at the instance first, and keep the HTTP Basic Auth gate in place so the API stays authenticated over TLS.

Persistence, first boot and updates

LanguageTool is stateless: it keeps no data between requests, so there is no database and no data volume to manage. The per instance password is generated once, on first boot, by languagetool-firstboot.service, which then disables itself; rebooting the instance does not regenerate it. To rotate the password, generate a new bcrypt entry with htpasswd -B /etc/nginx/.languagetool.htpasswd admin and restart nginx. Keep the base operating system patched with sudo apt-get update && sudo apt-get upgrade.

Support

Every cloudimg deployment is backed by 24/7 support from cloudimg engineers by email at support@cloudimg.co.uk and live chat, with a one hour average response for critical issues. Support covers deployment and sizing, JVM heap and per request tuning, the nginx front door, TLS termination and source restriction, rotating the Basic Auth credential, adding the optional n-gram datasets, and LanguageTool upgrades and troubleshooting.