Artificial Intelligence (AI) AWS

LibreTranslate on AWS User Guide

| Product: LibreTranslate on AWS

Overview

This image runs LibreTranslate 1.9.6, a free and open source machine translation engine you host yourself, installed from the project's official PyPI wheel into a dedicated Python virtualenv. LibreTranslate exposes a small REST API and a simple web interface, and it translates entirely on the instance using the offline Argos Translate neural models. Nothing you submit is sent to a third party service, and once the models are on disk the instance can translate with no internet access at all.

The engine is served by nginx over HTTPS on port 443, with LibreTranslate itself bound to the loopback interface only. Port 80 answers a plain HTTP liveness check at /health and 301-redirects everything else to port 443. HTTPS is not decoration here: the API key travels in the request body, so it should not cross a network in clear text.

The API ships key protected, not open. An open translation endpoint on the public internet is a compute abuse risk — anyone who finds it can spend your CPU. Key enforcement is therefore switched on, and it applies to the web interface as well as to programmatic callers. No usable key is baked into the image: on the first boot of every deployed instance a one-shot service generates a fresh random API key and a fresh self signed TLS certificate, unique to that instance, and writes the key to /root/libretranslate-info.txt with mode 0600.

Nine languages ship, as offline models: Arabic, Chinese, English, French, German, Italian, Portuguese, Russian and Spanish. That is a deliberate subset — the full upstream Argos catalogue is one hundred model packages and several further gigabytes. LibreTranslate pivots non English pairs through English, so all 72 cross language directional pairs across those nine resolve. Adding more languages is a documented, supported operation and is covered below.

The engine runs on CPU only. This image does not provide GPU acceleration, and LibreTranslate does not require it.

Storage is tiered across two dedicated EBS volumes so neither the models nor the runtime sit on the operating system disk: the Argos model store at /var/lib/libretranslate and the virtualenv at /opt/libretranslate. Both are mounted by filesystem UUID and each can be resized independently.

A note on what this is: LibreTranslate is a machine translation engine. Its output is well suited to understanding content, powering search, pre translating a catalogue or serving in product features where an automatic translation is appropriate. It is not human translation and it is not certified or sworn translation. Have output reviewed by a competent speaker before relying on it in a legal, medical or safety context.

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 security group allowing inbound TCP 22 from your own address, and TCP 443 from wherever your callers are

The recommended instance type is m5.large. Translation is CPU bound, so see the sizing section at the end before you commit to a size in production.

Connecting to your instance

Connect over SSH on port 22 using the key pair you selected at launch. The login user depends on the operating system variant you launched.

OS variant SSH login user Example
Ubuntu 24.04 LTS ubuntu ssh -i your-key.pem ubuntu@<public-ip>

Replace <public-ip> with your instance's public IPv4 address and your-key.pem with the private key file for your EC2 key pair.

Confirm the service is running

Two systemd units make up the running stack: libretranslate (the engine) and nginx (the TLS reverse proxy).

systemctl is-active libretranslate nginx
active
active

Both are enabled, so they come back automatically after a reboot:

systemctl is-enabled libretranslate nginx
enabled
enabled

Confirm the version and licence of what is actually installed:

/opt/libretranslate/venv/bin/pip show libretranslate | grep -E '^(Name|Version|License):'
Name: libretranslate
Version: 1.9.6
License: GNU AFFERO GENERAL PUBLIC LICENSE

The plain HTTP liveness endpoint answers without touching the application, which makes it a good target for a load balancer health check:

curl -s -o /dev/null -w 'HTTP %{http_code}\n' http://127.0.0.1/health
HTTP 200

Check what is listening. LibreTranslate is on loopback only; nginx owns the public ports:

sudo ss -tlnp | grep -E ':(80|443|5000)\b'
LISTEN 0      1024       127.0.0.1:5000      0.0.0.0:*    users:(("libretranslate",pid=5521,fd=7))
LISTEN 0      511          0.0.0.0:80        0.0.0.0:*    users:(("nginx",pid=5527,fd=5),("nginx",pid=5526,fd=5),("nginx",pid=5525,fd=5))
LISTEN 0      511          0.0.0.0:443       0.0.0.0:*    users:(("nginx",pid=5527,fd=7),("nginx",pid=5526,fd=7),("nginx",pid=5525,fd=7))
LISTEN 0      511             [::]:80           [::]:*    users:(("nginx",pid=5527,fd=6),("nginx",pid=5526,fd=6),("nginx",pid=5525,fd=6))
LISTEN 0      511             [::]:443          [::]:*    users:(("nginx",pid=5527,fd=8),("nginx",pid=5526,fd=8),("nginx",pid=5525,fd=8))

Your per instance API key

The key was generated on this instance's first boot and is stored in a root only file. You can list the field names in that file without revealing any value:

sudo grep -oE '^[A-Z0-9_]+=' /root/libretranslate-info.txt
LIBRETRANSLATE_API_KEY=
LIBRETRANSLATE_URL=
LIBRETRANSLATE_API_URL=
NOTE=
NOTE2=

To read the key itself, so you can paste it into the web interface or into your own client, run sudo cat /root/libretranslate-info.txt on the instance. That file also records the instance URL and a worked curl example.

Treat the key as a secret: do not commit it, and do not echo it in shell scripts or CI logs. Every example below reads it into a shell variable rather than printing it, which is the habit worth keeping.

The endpoint is closed without a key

This is worth verifying yourself rather than taking on trust. A translation request with no key is refused:

curl -ks -o /dev/null -w 'unauthenticated POST /translate -> HTTP %{http_code}\n' -X POST https://127.0.0.1/translate --data "q=Hello world&source=en&target=es&format=text"
unauthenticated POST /translate -> HTTP 400

LibreTranslate answers 400 when a key is required but absent, and 403 for a key it does not recognise. The web interface is subject to the same rule: open it without setting a key and it will tell you to contact the server operator for one.

Your first translation

Read the key into a variable and post a real translation. This is the round trip that proves the instance works:

KEY=$(sudo grep "^LIBRETRANSLATE_API_KEY=" /root/libretranslate-info.txt | cut -d= -f2-); curl -ks -X POST https://127.0.0.1/translate --data "q=Hello world&source=en&target=es&format=text&api_key=$KEY" | jq .
{
  "translatedText": "Hola mundo"
}

The -k flag is there because the instance ships a self signed certificate. Once you install a certificate for your own domain you can drop it.

Language detection works the same way:

KEY=$(sudo grep "^LIBRETRANSLATE_API_KEY=" /root/libretranslate-info.txt | cut -d= -f2-); curl -ks -X POST https://127.0.0.1/detect --data "q=Bonjour tout le monde&api_key=$KEY" | jq .
[
  {
    "confidence": 100.0,
    "language": "fr"
  }
]

From your own machine, substitute your instance's address for 127.0.0.1 and pass the key you read above:

curl -k -X POST https://<public-ip>/translate --data "q=Hello world&source=en&target=es&format=text&api_key=<your-api-key>"

The web interface

Browse to https://<public-ip>/ and accept the one time certificate warning. Choose your source and target languages, type into the left hand box, and the translation appears on the right.

LibreTranslate translating English to Spanish

Because key enforcement also covers the interface, click Set API Key in the header and paste the key from /root/libretranslate-info.txt the first time you use it. Until you do, the page loads but translation is refused:

A translation request refused because no API key is set

Non Latin scripts work exactly the same way:

LibreTranslate translating English to Chinese

The instance also serves an interactive REST API reference at https://<public-ip>/docs, listing every endpoint with its parameters and response shape:

The built in Swagger API reference served by the instance

Which languages ship

Ask the instance rather than guessing. /languages is the authoritative list:

curl -ks https://127.0.0.1/languages | jq -r '.[] | "\(.code)\t\(.name)"'
en  English
ar  Arabic
zh-Hans Chinese
fr  French
de  German
it  Italian
pt  Portuguese
ru  Russian
es  Spanish

Nine languages, and every one is reachable from every other:

curl -ks https://127.0.0.1/languages | jq '{languages: length, cross_language_pairs: (([.[].targets|length]|add) - length)}'
{
  "languages": 9,
  "cross_language_pairs": 72
}

Note the code for Chinese is zh-Hans, the script qualified form. LibreTranslate also accepts the plain zh on /translate, but /languages reports zh-Hans, so match on the prefix if your client builds its language menu from that response.

Those 72 pairs come from 18 Argos model packages — English to and from each of the other eight languages, plus two direct Spanish and Portuguese pairs. LibreTranslate pivots anything else through English, which is why French to German works without a French to German model:

sudo find /var/lib/libretranslate/argos-packages -maxdepth 2 -name metadata.json -type f | wc -l
18

A manifest of exactly which packages are installed is written onto the instance at /var/lib/libretranslate/argos-manifest.txt.

Adding more languages

The full upstream Argos catalogue is one hundred packages. To add one, install it with argospm as the service user, then widen the set the service loads and restart. This example adds Japanese; the model volume is sized for the entire catalogue, so you will not run out of room.

sudo -u libretranslate env HOME=/var/lib/libretranslate ARGOS_PACKAGES_DIR=/var/lib/libretranslate/argos-packages /opt/libretranslate/venv/bin/argospm install translate-en_ja

The service is started with a --load-only list naming the languages it loads into memory. Edit that list in the unit file to include your new language code, then reload and restart:

sudo sed -i 's/--load-only ar,de,en,es,fr,it,pt,ru,zh/--load-only ar,de,en,es,fr,it,pt,ru,zh,ja/' /etc/systemd/system/libretranslate.service && sudo systemctl daemon-reload && sudo systemctl restart libretranslate

Each loaded language costs memory, so add what you need rather than everything, and size the instance accordingly. Confirm the result with /languages again.

Issuing additional API keys

The keys live in a small SQLite database at /var/lib/libretranslate/api_keys.db, with a per key request limit. A freshly launched instance holds exactly the one key first boot generated:

sudo sqlite3 /var/lib/libretranslate/api_keys.db "SELECT count(*) AS keys, min(req_limit) AS req_limit FROM api_keys;"
1|80

Issuing a second key — for a different application, so you can revoke one without disturbing the other — is a single insert. This writes the new key straight into the root only file rather than printing it:

NEWKEY=$(python3 -c 'import uuid;print(uuid.uuid4())'); sudo sqlite3 /var/lib/libretranslate/api_keys.db "INSERT INTO api_keys (api_key, req_limit) VALUES ('$NEWKEY', 80);" && sudo sh -c "umask 077; printf 'SECOND_API_KEY=%s\n' '$NEWKEY' >> /root/libretranslate-info.txt" && echo "second key issued and appended to /root/libretranslate-info.txt"
second key issued and appended to /root/libretranslate-info.txt

Read it back from /root/libretranslate-info.txt when you need it, and give each application its own key so that revoking one never disturbs another. To revoke, delete the row whose key you are retiring — substitute the key itself for <your-api-key>:

sudo sqlite3 /var/lib/libretranslate/api_keys.db "DELETE FROM api_keys WHERE api_key = '<your-api-key>';"

Changes take effect on the next request; no restart is needed.

Replacing the self signed certificate

The certificate generated on first boot is self signed, which is why browsers warn and curl needs -k. Replace it with a certificate for a domain you control. Point a DNS A record at the instance, open port 80 to the internet so the HTTP-01 challenge can complete, then:

sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d translate.your-domain.example

Certbot rewrites the nginx server block and installs a renewal timer. If you would rather drop in a certificate you already hold, replace these two files and reload nginx — the paths are what the shipped configuration references:

sudo install -m 0644 -o root -g root your-fullchain.pem /etc/nginx/ssl/libretranslate.crt
sudo install -m 0600 -o root -g root your-private-key.pem /etc/nginx/ssl/libretranslate.key
sudo nginx -t && sudo systemctl reload nginx

Storage layout

Neither the models nor the runtime live on the operating system disk:

df -h --output=target,source,size,used,avail / /opt/libretranslate /var/lib/libretranslate
Mounted on              Filesystem      Size  Used Avail
/                       /dev/root        38G  3.7G   35G
/opt/libretranslate     /dev/nvme1n1    9.8G  474M  8.8G
/var/lib/libretranslate /dev/nvme2n1     40G  3.9G   34G

Both data volumes are referenced in /etc/fstab by filesystem UUID, so the layout reproduces on every instance launched from this image and survives device renaming. To grow either one, modify the EBS volume in the console and then run sudo resize2fs against the device shown above.

The only state worth backing up is /var/lib/libretranslate — it holds the models and your API keys. An EBS snapshot of that volume is sufficient.

Rate limits and tuning

The service starts with a request limit of 80 per minute per key and a 5000 character cap per request, and it runs two translation threads. All three are arguments in the unit file:

grep -E 'req-limit|char-limit|threads' /etc/systemd/system/libretranslate.service
    --req-limit 80 --char-limit 5000 --threads 2

Raise --threads towards the instance's vCPU count if you are throughput bound and have memory to spare, then sudo systemctl daemon-reload && sudo systemctl restart libretranslate. Raise --char-limit if you submit long documents, bearing in mind a single large request occupies a thread for its whole duration.

Sizing for throughput

Translation here is CPU bound, with no GPU involved. Two properties follow, and both matter more than instance family choice:

  • Throughput scales with vCPU count and with --threads. If you need more translations per second, add vCPUs and raise the thread count together; raising one without the other will not help.
  • Memory scales with the number of languages loaded, not with request volume. Each language in --load-only is held in memory. Loading the full catalogue on a small instance is the most common way to run out of RAM.

For bulk work, batching many short requests concurrently against a larger instance is more efficient than sending one very long request, because a single request cannot use more than one thread. If you need horizontal scale, run several instances behind a load balancer pointed at the /health endpoint on port 80 — the service holds no shared state, so instances are interchangeable, though each has its own key database and you will want to issue the same key on each.

Licensing

LibreTranslate is licensed under the GNU AGPL-3.0. The complete corresponding source of the installed version is shipped on the instance to satisfy AGPL Section 13:

ls /opt/libretranslate/src/libretranslate-1.9.6/LICENSE
/opt/libretranslate/src/libretranslate-1.9.6/LICENSE

The Argos Translate library is separately dual licensed MIT or CC0. The Argos model packages are distributed by the Argos Open Tech project through its package index, which publishes no per package licence field, so no licence claim is made here about the model weights themselves; the manifest on the instance identifies exactly which packages are installed and where they came from.

cloudimg is not affiliated with, endorsed by or sponsored by the LibreTranslate or Argos Open Tech projects.

Support

cloudimg provides 24/7 technical support for this image by email and live chat at support@cloudimg.co.uk. We aim to respond within one business day.

We can help with deployment and initial configuration, retrieving and rotating the per instance API key, issuing additional keys with their own rate limits, adding and loading further language models, replacing the self signed certificate and serving the API on your own domain, rate limit and thread tuning, growing the storage volumes, and sizing guidance for throughput.