LibreTranslate on Ubuntu 24.04 on Azure User Guide
Overview
LibreTranslate is a free and open source machine translation API that you run entirely inside your own Azure subscription. Powered by the offline Argos Translate neural models, it translates text between languages with no third party service in the loop and no data leaving your virtual machine, and it exposes both a clean REST API and a simple web interface.
The cloudimg image installs LibreTranslate (verified at 1.9.6) into a dedicated Python virtual environment at /opt/libretranslate/venv, running CPU only as the non root libretranslate service bound to loopback 127.0.0.1:5000, behind nginx on port 80. nginx is ready for your TLS certificate.
Offline models baked in. The Argos language models for a subset of common languages are pre installed into the image, so translation works the moment the machine boots, with no download and no GPU. The bundled languages are Arabic, Chinese, English, French, German, Italian, Portuguese, Russian and Spanish. LibreTranslate pivots pairs that do not have a direct model through English. You can add more languages at any time (see the section below).
Secure by default, no open endpoint. An open translation endpoint is a compute abuse risk, so this image enables API key enforcement: every translation request requires a key, including from the web interface, where you paste it once. A libretranslate-firstboot.service oneshot generates a unique API key on each VM's first boot, writes it to a root only file, resolves the instance URL and writes a root only info note, then hands off to the service. No two VMs share a key and none is baked into the image. Request rate and character limits guard against abuse, and LibreTranslate binds only to loopback so nginx is the single public listener.
What is included:
- LibreTranslate (verified at 1.9.6) in a dedicated Python virtual environment, CPU only
libretranslate.servicebound to127.0.0.1:5000, behind nginx on port 80, ready for TLS- Offline Argos models for 9 common languages, pre installed for out of the box translation
libretranslate-firstboot.servicefor the first boot API key, URL resolution and info note- A unique per VM API key generated on first boot, in a root only
0600file - Ubuntu 24.04 LTS base, fully patched, unattended security upgrades enabled
- 24/7 cloudimg support, 24h response SLA
Prerequisites
An active Azure subscription, an SSH key pair, and a VNet with a subnet. LibreTranslate runs on CPU alone; translation throughput scales with CPU and memory. Recommended VM size: Standard_B2s (2 vCPU, 4 GB RAM) for evaluation and light use, or a Standard_D2s_v5 / Standard_F4s_v2 or larger for heavier translation volume. The models live on the OS disk, so expand the disk before loading many additional languages.
Step 1: Deploy from the Azure Portal
Search the Marketplace for LibreTranslate on Ubuntu 24.04, choose your VM size, and attach an NSG that allows TCP 22 (SSH) from your management network and TCP 80 / 443 (the translation service) from the networks and applications that need to reach it. Front port 80 with TLS in production (see the HTTPS section below).
Step 2: Deploy from the Azure CLI
RG="libretranslate-prod"; LOCATION="eastus"; VM_NAME="libretranslate-01"
GALLERY_IMAGE_ID="/subscriptions/<sub-id>/resourceGroups/azure-cloudimg/providers/Microsoft.Compute/galleries/cloudimgGallery/images/libretranslate-ubuntu-24-04/versions/<version>"
SSH_KEY="$(cat ~/.ssh/id_rsa.pub)"
az group create --name "$RG" --location "$LOCATION"
az network vnet create -g "$RG" --name lt-vnet --address-prefix 10.90.0.0/16 --subnet-name lt-subnet --subnet-prefix 10.90.1.0/24
az network nsg create -g "$RG" --name lt-nsg
az network nsg rule create -g "$RG" --nsg-name lt-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 lt-nsg --name allow-web --priority 110 \
--source-address-prefixes "<your-mgmt-cidr>" --destination-port-ranges 80 443 --access Allow --protocol Tcp
az vm create -g "$RG" --name "$VM_NAME" --image "$GALLERY_IMAGE_ID" \
--size Standard_B2s --storage-sku StandardSSD_LRS \
--admin-username azureuser --ssh-key-values "$SSH_KEY" \
--vnet-name lt-vnet --subnet lt-subnet --nsg lt-nsg --public-ip-sku Standard
Step 3: Connect via SSH
ssh azureuser@<vm-ip>
Step 4: Verify the services
LibreTranslate and nginx start automatically after the first boot service has generated the per VM key. Confirm the stack is healthy:
systemctl is-active libretranslate.service nginx.service
ss -tlnp | grep -E ':80 |:5000 '
You should see both services active, nginx listening on port 80 for the world, and LibreTranslate listening only on 127.0.0.1:5000 — it is never exposed directly.

Step 5: Retrieve your per-VM API key
Every translation request needs the API key that was generated uniquely for this VM on its first boot. It lives in a root only file:
sudo cat /root/libretranslate-info.txt
The LIBRETRANSLATE_API_KEY value is yours alone — no other VM has it, and it is not present in the Marketplace image. Keep it secret. LIBRETRANSLATE_URL is the address of your instance.

Step 6: Translate from the web interface
Open http://<vm-ip>/ in a browser. The LibreTranslate interface loads immediately. Because the service is secured, click the key icon (Set API Key) in the top navigation bar and paste the LIBRETRANSLATE_API_KEY from Step 5. Your key is stored in the browser and sent with every translation.
Now pick your languages, type into the left pane, and the translation appears on the right. Below, English to Spanish returns "Hola mundo":

The same interface handles every bundled language. Here a full sentence is translated from English into French, entirely offline on the VM:

Step 7: Translate through the REST API
The same translation is available over HTTP. First confirm the endpoint is closed without a key — this is the secure default — then send an authenticated request that reads the per VM key from the info file:
# Without a key: the request is rejected (no open translation endpoint)
curl -s -X POST http://127.0.0.1/translate \
--data 'q=Hello world&source=en&target=es&format=text' | jq .
# With your per-VM key: a real offline translation
API_KEY=$(sudo grep '^LIBRETRANSLATE_API_KEY=' /root/libretranslate-info.txt | cut -d= -f2-)
curl -s -X POST http://127.0.0.1/translate \
--data "q=Hello world&source=en&target=es&format=text&api_key=$API_KEY" | jq .
The unauthenticated call returns {"error": "Please contact the server operator to get an API key"}; the authenticated call returns {"translatedText": "Hola mundo"}.

From your own application, send the key as the api_key field (or replace <your-api-key> with the value from Step 5):
curl -s -X POST http://<vm-ip>/translate \
--data 'q=Good morning&source=en&target=fr&format=text&api_key=<your-api-key>' | jq -r '.translatedText'
Step 8: The bundled languages, and adding more
List the languages that are loaded and ready to translate offline. The keyRequired flag in the frontend settings confirms the service is secured:
curl -s http://127.0.0.1/languages | jq -r '.[] | .code + " " + .name'
curl -s http://127.0.0.1/frontend/settings | jq '{apiKeys, keyRequired, charLimit}'

To add another language, install its Argos model as the libretranslate service user and widen the service's --load-only list. For example, to add Japanese (ja):
# Install the model (installs into the service's offline model store)
sudo -u libretranslate env HOME=/var/lib/libretranslate \
ARGOS_PACKAGES_DIR=/var/lib/libretranslate/argos-packages \
/opt/libretranslate/venv/bin/python -c \
"from argostranslate import package; package.update_package_index(); \
p=[x for x in package.get_available_packages() if x.from_code in ('en','ja') and x.to_code in ('en','ja')]; \
[package.install_from_path(x.download()) for x in p]"
# Add ja to the --load-only list in the service unit, then restart
sudo sed -i 's/--load-only ar,de,en,es,fr,it,pt,ru,zh/--load-only ar,de,en,es,fr,it,ja,pt,ru,zh/' \
/etc/systemd/system/libretranslate.service
sudo systemctl daemon-reload && sudo systemctl restart libretranslate.service
Removing a language from --load-only unloads it without deleting the model, which lowers memory use.
Step 9: Explore the built-in API documentation
LibreTranslate ships interactive REST API documentation at /docs, covering /translate, /detect, /languages and file translation, with request and response schemas.

Step 10: Enable HTTPS
nginx fronts LibreTranslate on port 80 and is ready for your TLS certificate. For a public hostname, install a Let's Encrypt certificate with certbot:
sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.example.com
certbot obtains the certificate, rewrites the nginx server block for TLS, and sets up automatic renewal. Point port 443 at your management and application networks in the NSG, and restrict port 80 to the redirect.
Managing the service
systemctl status libretranslate.service # service health
sudo journalctl -u libretranslate.service -f # live logs
sudo systemctl restart libretranslate.service
Configuration lives in the systemd unit /etc/systemd/system/libretranslate.service (host, port, --load-only, --req-limit, --char-limit). The API keys database is /var/lib/libretranslate/api_keys.db.
Support
This image is backed by 24/7 cloudimg support with a 24 hour response SLA. LibreTranslate is licensed under the GNU AGPL-3.0. For product questions, consult the LibreTranslate documentation.