Deploy: LanguageTool spell checker in production, with optional n-grams
- docker-compose.yml: a `languagetool` service (erikvl87/languagetool:6.8),
internal only, 1 GB heap, one CPU, a 28 GB memory limit that is room for the
n-gram page cache (reclaimable, not memory in use), and a low-priority
warm-up read of the n-gram files at start so first checks hit RAM even on
mechanical disks. `init` creates $DATA_ROOT/languagetool-ngrams; the app
containers get LANGUAGETOOL_URL (empty turns the check off).
- `webmail.sh ngrams [langs]` (default en de fr es): deploy/ngrams.py, run in
the backend image, downloads LanguageTool's n-gram data with resume, checks
free space first (unpacked is ~2x the zip: ~26 GB for all four), unpacks into
a temp folder and moves it into place, then recreates the engine to load it.
languagetool.org refuses Python's default User-Agent, so it sends its own.
- `doctor` reports whether the spell checker answers and which n-gram
languages are installed.
- docs/nas-install.md and .env.prod.example describe all of it.
Verified locally: German n-grams (1.58 GB -> 3.06 GB) load, and catch what the
rules alone do not ("liegt ihm Schrank" -> im, "Der Patenten" -> Patienten).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
# ./deploy/webmail.sh backup take a verified database dump now
|
||||
# ./deploy/webmail.sh restore <file> DESTRUCTIVE: restore a dump
|
||||
# ./deploy/webmail.sh reindex [args] rebuild the search index from Postgres
|
||||
# ./deploy/webmail.sh ngrams [langs] download spell-check n-gram data (default: en de fr es)
|
||||
# ./deploy/webmail.sh psql open a database shell
|
||||
# ./deploy/webmail.sh shell [svc] shell inside a container (default: api)
|
||||
# ./deploy/webmail.sh show-key print MASTER_KEY so you can back it up
|
||||
@@ -418,6 +419,23 @@ print('AUTHORISED')
|
||||
ylw " antispam is not in ENABLED_PLUGINS — no spam filtering on this install" ;;
|
||||
esac
|
||||
|
||||
# Spelling/grammar check: is the engine answering, and with which n-grams?
|
||||
lt="$(compose exec -T api python -c "
|
||||
import os, urllib.request
|
||||
url = os.environ.get('LANGUAGETOOL_URL', '')
|
||||
print('OFF' if not url else urllib.request.urlopen(url + '/v2/languages', timeout=5).status)
|
||||
" 2>&1 | tail -1)" || true
|
||||
ngrams=""
|
||||
for d in "${DATA_ROOT}/languagetool-ngrams"/*/; do
|
||||
[ -d "${d}3grams" ] && ngrams="${ngrams} $(basename "$d")"
|
||||
done
|
||||
case "$lt" in
|
||||
200) grn " spell check engine answering; n-grams:${ngrams:- none (optional: webmail.sh ngrams)}" ;;
|
||||
OFF) ylw " spell check is off (LANGUAGETOOL_URL is empty)" ;;
|
||||
*) ylw " spell check engine not answering — the compose window falls back to the browser's checker"
|
||||
printf ' %s\n' "$lt" ;;
|
||||
esac
|
||||
|
||||
if command -v ss >/dev/null 2>&1; then
|
||||
local p
|
||||
for p in "WEB_PORT:${WEB_PORT:-8088}" "ADMIN_PORT:${ADMIN_PORT:-8089}"; do
|
||||
@@ -675,6 +693,23 @@ cmd_show_key() {
|
||||
}
|
||||
|
||||
cmd_reindex() { require_env; compose run --rm api reindex "$@"; }
|
||||
|
||||
# Optional n-gram data for the spell checker (~13 GB download for en de fr es):
|
||||
# lets LanguageTool catch real words used wrongly ("loose weight", "das er
|
||||
# kommt"). Downloaded and unpacked by deploy/ngrams.py inside the backend image
|
||||
# (it resumes an interrupted download — just run it again), then the engine is
|
||||
# recreated to load it. Polish has no n-gram data; it is checked as before.
|
||||
cmd_ngrams() {
|
||||
require_env
|
||||
local dir="${DATA_ROOT}/languagetool-ngrams"
|
||||
mkdir -p "$dir" || die "cannot create ${dir} (run as the owner of DATA_ROOT, or as root)"
|
||||
echo "== downloading n-gram data into ${dir} (${*:-en de fr es})"
|
||||
compose run --rm --no-deps -T --user 0 -v "${dir}:/ngrams" --entrypoint python api - "$@" \
|
||||
< "${SCRIPT_DIR}/ngrams.py" || die "n-gram download failed — run the same command again to resume"
|
||||
echo "== restarting the spell checker to load it"
|
||||
compose up -d --no-deps --force-recreate languagetool
|
||||
grn "n-grams installed. It reads them into memory in the background over the next minutes."
|
||||
}
|
||||
cmd_psql() { require_env; compose exec postgres psql -U "${POSTGRES_USER:-webmail}" -d "${POSTGRES_DB:-webmail}"; }
|
||||
cmd_shell() { require_env; compose exec "${1:-api}" /bin/sh; }
|
||||
|
||||
@@ -700,6 +735,7 @@ case "$cmd" in
|
||||
backup) cmd_backup "$@" ;;
|
||||
restore) cmd_restore "$@" ;;
|
||||
reindex) cmd_reindex "$@" ;;
|
||||
ngrams) cmd_ngrams "$@" ;;
|
||||
show-key) cmd_show_key "$@" ;;
|
||||
psql) cmd_psql "$@" ;;
|
||||
shell) cmd_shell "$@" ;;
|
||||
|
||||
Reference in New Issue
Block a user