---
title: "Deploy LanguageTool"
description: "Grammar, style and spell checking API for more than 30 languages"
category: "Other"
url: https://railway.com/deploy/languagetool
---

# Deploy LanguageTool

Grammar, style and spell checking API for more than 30 languages

**[Deploy LanguageTool on Railway](https://railway.com/template/languagetool)**

Machine-readable deploy manifest (JSON, validated by TemplateCI): https://railway.com/deploy/languagetool/manifest.json

- **Creator:** A3A
- **Category:** Other

## Template content

### MySQL https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/mysql.svg

- **Image:** mysql:9.4
- **Start command:** `docker-entrypoint.sh mysqld --innodb-use-native-aio=0 --disable-log-bin --performance_schema=0 --innodb-buffer-pool-size=1G`

### gateway https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/caddy.svg

- **Source:** https://github.com/gridalpha/languagetool-railway
- **Health check:** /healthz
- **Public domain:** Yes

### languagetool https://cdn.simpleicons.org/languagetool/white.svg

- **Source:** https://github.com/gridalpha/languagetool-railway
- **Health check:** /v2/languages

## Documentation

# Deploy and Host LanguageTool on Railway

LanguageTool is an open-source proofreading engine that finds grammar, style, punctuation and spelling mistakes in more than 30 languages, and it powers the LanguageTool browser add-ons, the LibreOffice integration and dozens of editor plugins. Unlike a spell checker it reasons about context, catching confused words, agreement errors and awkward phrasing a dictionary lookup never will. Teams self-host LanguageTool to get that quality without sending drafts or customer documents to a third-party writing service.

Deploy LanguageTool on Railway and you get the complete HTTP API, not a trimmed demo. The template runs three services: `languagetool` is the Java API server on the private network, `MySQL` stores API keys and per-account dictionaries, and `gateway` is the public entry point — a Caddy reverse proxy that serves a browser console and rewrites `X-Forwarded-For` so the per-IP rate limiter sees real callers rather than the platform edge. Self-host LanguageTool this way and the API starts closed: anonymous requests are rejected.

![Diagram of the LanguageTool, gateway and MySQL services on Railway](https://res.cloudinary.com/rroe4rtk/image/upload/v1788480840/languagetool-architecture.png)

## Getting Started with LanguageTool on Railway

Deploy the template, wait for all three services to go green, then open the `gateway` service's public URL. You land on a console that reports the running LanguageTool version once it reaches the API. Paste the credentials first: the username and API key are the `LT_API_USERNAME` and `LT_API_KEY` variables on the `languagetool` service, and the console keeps them in your browser only. Type a paragraph, pick a language — or leave it on automatic detection, handled by the bundled fastText model — and press **Check text**. Each finding comes back with the rule that fired, the sentence context and clickable replacements; clicking one rewrites your text and re-runs the check. Then add a word such as a product name to the personal dictionary and check again: it stops being flagged, because that word is now a row in MySQL tied to your account. That round trip exercises all three services at once.

![LanguageTool console checking a paragraph of misspelled English](https://res.cloudinary.com/rroe4rtk/image/upload/v1788480843/languagetool-check-results.png)
![Grammar and spelling corrections offered for each flagged phrase](https://res.cloudinary.com/rroe4rtk/image/upload/v1788480844/languagetool-suggestions.png)
![Personal dictionary words accepted by a later spell check](https://res.cloudinary.com/rroe4rtk/image/upload/v1788480846/languagetool-personal-dictionary.png)

## About Hosting LanguageTool

LanguageTool combines a rule engine, hand-written grammar patterns and morphological dictionaries into one JVM service that answers `POST /v2/check` with a JSON list of matches. Self-hosting matters when the text is confidential, when you need volume without per-seat pricing, or when you want your own terminology.

- More than 30 languages, including variants such as `en-US`, `en-GB`, `de-DE` and `pt-BR`
- Context-aware grammar and style rules, with a stricter `picky` level
- Automatic language detection via a bundled fastText model
- Per-account dictionaries through `/v2/words`, `/v2/words/add` and `/v2/words/delete`
- API-key authentication, per-IP request limits and a maximum text length

`languagetool` does the analysis and holds no local state, so it restarts without losing anything. `MySQL` holds the two tables the server reads: accounts with their API keys, and the words each account told the checker to ignore. `gateway` is the only service with a public domain.

## Why Deploy LanguageTool on Railway

Railway removes the setup work that makes self-hosting a grammar server unattractive.

- Managed MySQL, provisioned and wired to the API server automatically
- No JVM tuning: the heap is sized from the container's real memory limit
- HTTPS, a public domain and health checks configured out of the box
- API-key authentication enforced from the first request

## Common Use Cases for Self-Hosted LanguageTool

- **Editorial pipelines** — proofread articles or release notes in CI and fail a build on unresolved issues
- **Support tooling** — check agent replies before sending, without routing conversations through an external service
- **CMS and editor integrations** — back a "check my text" button in your own app, or point plugins at an endpoint you control
- **Regulated environments** — proofread inside your own network, where a hosted checker is not allowed

## LanguageTool vs Grammarly and Other Grammar Checkers

| | LanguageTool (self-hosted) | Grammarly |
|---|---|---|
| Self-hosting | Yes, LGPL-2.1 | No |
| Languages | 30+ | English only |
| API access | Open JSON API | Enterprise only |
| Per-seat cost | None | From ~$12/user/month |
| Custom dictionary | In your database | Vendor cloud |

Grammarly is stronger at English rewriting; LanguageTool wins on language coverage, data control and cost once more than a few people need it.

## Dependencies for LanguageTool on Railway

- **languagetool** — built from `erikvl87/languagetool`, the community image packaging each upstream release
- **gateway** — `caddy:2-alpine`, the public reverse proxy and console
- **MySQL** — `mysql:9.4`, the account and dictionary store

### Environment Variables Reference

| Variable | Service | What it does |
|---|---|---|
| `LT_API_USERNAME` | languagetool | Username callers send as `username` |
| `LT_API_KEY` | languagetool | Secret callers send as `apiKey` |
| `langtool_anonymousAccessAllowed` | languagetool | `false` closes the API; `true` opens it |
| `langtool_requestLimit` | languagetool | Requests allowed per client IP per period |
| `langtool_maxTextLength` | languagetool | Maximum characters in one request |
| `langtool_languageModel` | languagetool | Directory of n-gram data, if you add a volume |
| `Java_Xmx` | languagetool | Overrides the derived JVM heap size |

### Deployment Dependencies

- Source repository: [github.com/gridalpha/languagetool-railway](https://github.com/gridalpha/languagetool-railway)
- Upstream project: [github.com/languagetool-org/languagetool](https://github.com/languagetool-org/languagetool)
- API documentation: [languagetool.org/http-api](https://languagetool.org/http-api/)
- Base image: [hub.docker.com/r/erikvl87/languagetool](https://hub.docker.com/r/erikvl87/languagetool)

## Hardware Requirements for Self-Hosting LanguageTool

| | Minimum | Recommended |
|---|---|---|
| CPU | 1 vCPU | 2–4 vCPU |
| RAM | 1 GB | 2–4 GB for the API server |
| Storage | None for the API server | 5 GB for MySQL |
| Runtime | Java 17 | Java 17 |

Memory is the number that matters: LanguageTool loads dictionaries and rule sets per language on first use, so one language fits in 1 GB while a multilingual server wants 4 GB.

## Self-Hosting LanguageTool with Docker

To run the same image locally, start the community container on port 8010:

```
docker run --rm -p 8010:8010 \
  -e Java_Xms=512m -e Java_Xmx=2g \
  -e langtool_pipelineCaching=true \
  erikvl87/languagetool
```

Any LanguageTool client speaks the same endpoint. This checks one sentence, using the credentials from the Railway variables:

```
curl -s https://your-app.up.railway.app/v2/check \
  --data "language=en-US" \
  --data-urlencode "text=She dont know weather to chose the blue one." \
  --data "username=apiuser" \
  --data "apiKey=YOUR_LT_API_KEY"
```

Editor integrations that accept a custom server URL — LTeX for VS Code, the Obsidian plugin, Joplin, Nextcloud Text — point at the same origin.

## How Much Does LanguageTool Cost to Self-Host?

LanguageTool's server is free and open source under LGPL-2.1, so there is no licence fee and no per-seat charge however many people or services call it. Hosted LanguageTool Premium runs from roughly $5 to $25 per user per month; self-hosting replaces that with infrastructure cost alone. On Railway you pay for the API server's memory, the proxy and the MySQL volume. Premium-only rules and AI rewriting are not in the open-source build.

## FAQ

**What is LanguageTool?**
An open-source proofreading service that checks text for grammar, style, punctuation and spelling errors in over 30 languages, exposed as a JSON HTTP API used by browser add-ons, office suites and editor plugins.

**What does this Railway template deploy?**
Three services: the LanguageTool API server, a MySQL database holding API keys and dictionaries, and a Caddy gateway publishing the API and a browser console on one HTTPS domain.

**Why does this template include a database?**
LanguageTool's open-source server reads accounts and their API keys from MySQL — that lookup is what makes `langtool_anonymousAccessAllowed=false` possible — and the same database stores each account's dictionary. Without it there is no way to close the API or teach it your own terminology.

**How do I authenticate requests to a self-hosted LanguageTool server?**
Send `username` and `apiKey` as form parameters alongside `text` and `language`, using the values in `LT_API_USERNAME` and `LT_API_KEY`. To add another caller, insert a row into the `users` table with a different key.

**Can I use the confused-word rules that need n-gram data?**
Not by default: that data set is about 8.9 GB for English alone. Attach a large volume, unpack the data into it and point `langtool_languageModel` at the mount path.

**How do I connect the LanguageTool browser extension to my own server?**
Set the add-on's server URL to your deployment's domain. The add-on sends no API key, so switch `langtool_anonymousAccessAllowed` to `true` first — which makes the endpoint usable by anyone with the URL, so treat it as a deliberate choice.


## Similar templates

- [Rocky Linux](https://railway.com/deploy/rocky-linux) — Hosted Rocky Linux 9 workspace with SSH and persistent storage. 🚀
- [Foundry Virtual Tabletop](https://railway.com/deploy/X5tR6G) — A Self-Hosted & Modern Roleplaying Platform
- [Letta Code Remote](https://railway.com/deploy/letta-code-remote) — Run a Letta Code agent 24/7. No inbound ports, just deploy.

Open this page in a browser: https://railway.com/deploy/languagetool
