LiteLLM 1.88.0
Overview
This guide shows how to launch and verify LiteLLM 1.88.0 on Ubuntu 24.04 from SecureAnyCloud on Amazon EC2. It is one version in the SecureAnyCloud Hardened Ollama, LiteLLM & Self Hosted LLM Server AMIs listing on AWS Marketplace. You choose it as the software version when you subscribe and launch. The listing's guide hub describes the other LLM servers, gateways and chat interfaces in the listing.
LiteLLM is an open-source LLM gateway. It puts one OpenAI-compatible API (/v1/chat/completions, /v1/embeddings, /v1/models and the rest) in front of more than 100 model providers: OpenAI, Anthropic, Amazon Bedrock, Azure OpenAI, Google Vertex AI, Mistral, Ollama and many more. Your applications call one endpoint with one key. You change or load-balance the providers behind it in a configuration file, without touching client code.
The image ships no model weights and no GPU libraries. LiteLLM forwards requests to the providers you configure, so a small CPU instance is enough.
What you get:
- LiteLLM 1.88.0 (the MIT-licensed proxy core) in a Python 3.12 virtual environment at
/opt/litellm/venv, run bylitellm.serviceas the unprivilegedlitellmuser - LiteLLM bound to loopback only (
127.0.0.1:4000), with nginx as the only network-facing service - HTTPS on port 443 with a self-signed certificate created on your instance's first boot, and port 80 redirecting to HTTPS
- A per-instance master key, salt key and UI password, generated on first boot into root-only files
- An empty model list in
/etc/litellm/config.yaml, ready for your providers litellm-set-hostname, a helper that serves LiteLLM under your own DNS name and re-issues the certificate for it
Default user: ubuntu. Architecture: x86_64. Root volume: 8 GiB gp3.
Security posture
- No default key. The master key (
LITELLM_MASTER_KEY), the salt key that encrypts stored provider credentials (LITELLM_SALT_KEY) and the UI password are generated on each instance's first boot. None of them exists in the image, so no two instances share one. - Keys are never in a world-readable file or on a command line. They live in
/etc/litellm/litellm-secrets.env(mode 0600, root) and systemd loads them.config.yamlrefers to the master key by name (os.environ/LITELLM_MASTER_KEY) and holds no secret. - Fails closed.
litellm.servicerefuses to start unless a well-formed per-instance master key exists. nginx does not start before first boot has created the keys. If first boot cannot prove that an anonymous call and a wrong key are refused and the master key is accepted, it stops nginx rather than leave the gateway open. - Every API and management route needs a key. Anonymous calls get
401. LiteLLM itself refuses a key it does not know, before any provider is contacted. - Only nginx faces the network. It answers only for the configured hostname, and closes the connection for any other
Hostheader. It uses TLS 1.2 or 1.3 and refuses cross-originPOSTrequests and WebSocket upgrades (403). It never passes LiteLLM's permissive CORS headers on, and it replaces any client-suppliedX-Forwarded-Forwith the real peer address. - The hostname comes from configuration, never from a request. First boot reads it from EC2 instance metadata (IMDSv2) or from
/etc/sac/litellm-hostname. - No instance metadata access for the gateway. LiteLLM fetches URLs on your behalf (provider
api_basevalues, image URLs in requests, pass-through and MCP targets). For this reasonlitellm.serviceis blocked from the instance metadata service (169.254.169.254 and fd00:ec2::254). A request can never read the instance's role credentials through the gateway. Amazon Time Sync (169.254.169.123) is unaffected. - IMDSv2 required. The AMI is registered with
ImdsSupport v2.0, so instances launched from it refuse token-less (IMDSv1) metadata requests. - MIT core only. The litellm[proxy] package depends on litellm-enterprise, which carries BerriAI's proprietary Enterprise licence. SecureAnyCloud removes it, and the build fails if any part of it remains. The open-source gateway features in this guide do not need it.
- Sandboxed service and per-instance identity.
litellm.serviceruns withNoNewPrivileges,ProtectSystem=full,ProtectHome,PrivateTmpandPrivateDevices. SSH host keys and the machine ID are generated fresh on every instance.
Prerequisites
- An AWS account and permission to launch EC2 instances
- An EC2 key pair in the Region you launch in
- API keys for the model providers you want LiteLLM to call (OpenAI, Anthropic, Bedrock and so on), or a self-hosted model server such as Ollama
Recommended instance type: m5.large. LiteLLM is a gateway and holds no model, so its 2 vCPUs and 8 GiB of memory are ample. The model work happens at your providers.
Connecting to your instance
Version Operating system SSH user
LiteLLM 1.88.0 on Ubuntu 24.04 Ubuntu 24.04 LTS ubuntu
Launch the instance
Option A: AWS Marketplace console
- Open the SecureAnyCloud Hardened Ollama, LiteLLM & Self Hosted LLM Server AMIs listing on AWS Marketplace. Choose View purchase options, then Subscribe. One subscription covers every version in the listing.
- When the subscription is active, choose Launch your software.
- Choose One-click launch from AWS Marketplace, or Launch from EC2 Console for the full launch wizard. In Version, choose LiteLLM 1.88.0 on Ubuntu 24.04, then choose your Region.
- Pick an instance type and your key pair.
m5.largeis recommended, and the software charge is $0.04 per vCPU per hour. - Set the security group. The listing's default group opens SSH (22), HTTP (80) and HTTPS (443). Restrict SSH to your own IP address, and restrict 80 and 443 to the networks that your applications call from.
- Choose your VPC and subnet, leave the metadata defaults (the image already requires IMDSv2), then choose Launch.
Option B: AWS CLI
Run these commands on your own workstation. They create a security group that allows SSH from your management address and HTTPS from your application network, then launch the instance. Replace the AMI ID with the one shown for your Region on the Marketplace launch page. Replace the VPC, subnet, key pair and CIDR ranges with your own:
SG=$(aws ec2 create-security-group --group-name litellm-gateway \
--description "LiteLLM gateway" --vpc-id vpc-0123456789abcdef0 \
--query GroupId --output text)
aws ec2 authorize-security-group-ingress --group-id "$SG" --protocol tcp --port 22 --cidr <your-mgmt-cidr>
aws ec2 authorize-security-group-ingress --group-id "$SG" --protocol tcp --port 443 --cidr 10.0.0.0/16
aws ec2 authorize-security-group-ingress --group-id "$SG" --protocol tcp --port 80 --cidr 10.0.0.0/16
aws ec2 run-instances \
--image-id ami-0123456789abcdef0 \
--instance-type m5.large \
--key-name my-key-pair \
--security-group-ids "$SG" \
--subnet-id subnet-0123456789abcdef0 \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=litellm-gateway}]'You do not need --metadata-options, because the AMI already requires IMDSv2.
Connect and find your keys
Connect as ubuntu with the key pair you chose:
ssh -i ~/.ssh/my-key-pair.pem ubuntu@<public-ip>First boot finishes within a minute of launch. It sets the hostname that LiteLLM is served as (the instance's public DNS name when it has one) and creates the TLS certificate for it. It also generates the keys, starts LiteLLM and nginx, and writes /root/litellm-credentials.txt. This command lists the entries in that file without showing the values:
sudo grep -E '^LITELLM_(HOST|URL|UI_USERNAME)=' /root/litellm-credentials.txt
sudo grep -oE '^[A-Z_]+=' /root/litellm-credentials.txtLITELLM_HOST=ec2-3-84-115-65.compute-1.amazonaws.com LITELLM_URL=https://ec2-3-84-115-65.compute-1.amazonaws.com/ LITELLM_UI_USERNAME=admin LITELLM_HOST= LITELLM_URL= LITELLM_MASTER_KEY= LITELLM_UI_USERNAME= LITELLM_UI_PASSWORD=To read your master key, run sudo cat /root/litellm-credentials.txt in your own session. LITELLM_MASTER_KEY (an sk- string) is the admin key for the whole gateway. Keep it secret and store it in your secrets manager.
Confirm the gateway is running
Run these checks to confirm that the first-boot unit, LiteLLM and nginx are active. They also confirm that the installed version is 1.88.0 under the MIT licence, and that only sshd and nginx listen beyond loopback. LiteLLM itself listens on 127.0.0.1:4000.
systemctl is-active litellm-firstboot.service litellm.service nginx.service /opt/litellm/venv/bin/pip show litellm | grep -E '^(Name|Version|License)'
sudo ss -Htlnp | awk '{print $4, $6}' | sed -E 's/,pid=[0-9]+,fd=[0-9]+//g' | sort -uactive active active Name: litellm Version: 1.88.0 License-Expression: MIT 0.0.0.0:22 users:(("sshd"),("systemd")) 0.0.0.0:443 users:(("nginx"),("nginx"),("nginx")) 0.0.0.0:80 users:(("nginx"),("nginx"),("nginx")) 127.0.0.1:4000 users:(("litellm")) 127.0.0.53%lo:53 users:(("systemd-resolve")) 127.0.0.54:53 users:(("systemd-resolve")) [::]:22 users:(("sshd"),("systemd")) [::]:443 users:(("nginx"),("nginx"),("nginx")) [::]:80 users:(("nginx"),("nginx"),("nginx"))Call the API with the master key
LiteLLM answers on https://<LITELLM_HOST>/. LiteLLM's own auth layer refuses an anonymous call, and the master key lists the configured models (none yet):
H=$(sudo grep '^LITELLM_HOST=' /root/litellm-credentials.txt | cut -d= -f2-)
KEY=$(sudo grep '^LITELLM_MASTER_KEY=' /root/litellm-credentials.txt | cut -d= -f2-)
curl -s --cacert /etc/ssl/litellm/litellm.crt "https://$H/health/liveliness"; echo
curl -s --cacert /etc/ssl/litellm/litellm.crt "https://$H/v1/models"; echo
curl -s --cacert /etc/ssl/litellm/litellm.crt "https://$H/v1/models" -H "Authorization: Bearer $KEY"; echo"I'm alive!" {"error":{"message":"Authentication Error, No api key passed in.","type":"auth_error","param":"None","code":"401"}} {"data":[],"object":"list"}From your own machine, copy the instance's certificate (/etc/ssl/litellm/litellm.crt) and pass it to your client, or add it to your trust store. Any OpenAI-compatible SDK works. Set its base URL to https://<LITELLM_HOST>/v1 and its API key to the master key (or, once you add a database, a virtual key).
Add your model providers
Define models in /etc/litellm/config.yaml. Keep provider keys in /etc/litellm/litellm-secrets.env (root-only), never in the YAML file. The shipped configuration is:
sudo grep -vE '^\s*#' /etc/litellm/config.yaml | sed '/^$/d'model_list: [] general_settings: master_key: os.environ/LITELLM_MASTER_KEY litellm_settings: drop_params: trueFor example, to offer OpenAI's gpt-4o and Anthropic's Claude Sonnet through the gateway, edit the file with sudo nano /etc/litellm/config.yaml. Replace model_list: [] with:
model_list: - model_name: gpt-4o litellm_params: model: openai/gpt-4o api_key: os.environ/OPENAI_API_KEY - model_name: claude-sonnet litellm_params: model: anthropic/claude-sonnet-4-5 api_key: os.environ/ANTHROPIC_API_KEYThen add the keys to the secrets file and restart LiteLLM:
sudo nano /etc/litellm/litellm-secrets.env
# add one line each for OPENAI_API_KEY and ANTHROPIC_API_KEY
sudo systemctl restart litellm.serviceA chat completion now goes through the gateway like any OpenAI call:
curl --cacert litellm.crt https://<LITELLM_HOST>/v1/chat/completions \
-H "Authorization: Bearer <master key>" -H 'Content-Type: application/json' \
-d '{"model":"gpt-4o","messages":[{"role":"user","content":"Hello"}]}'Self-hosted servers work the same way. An Ollama instance in your VPC is model: ollama/llama3.1 with api_base: http://<ollama-private-ip>:11434. The LiteLLM documentation lists the providers and the parameters for each one.
Virtual keys, budgets and the admin UI
Virtual keys, spend tracking and the admin UI at https://<LITELLM_HOST>/ui/ store their state in a PostgreSQL database. Virtual keys are scoped keys per application, with their own budgets, rate limits and model lists. This image does not configure a database, so out of the box the master key is the only key and the UI login reports that no database is connected. Asking for a virtual key shows the same:
H=$(sudo grep '^LITELLM_HOST=' /root/litellm-credentials.txt | cut -d= -f2-)
KEY=$(sudo grep '^LITELLM_MASTER_KEY=' /root/litellm-credentials.txt | cut -d= -f2-)
curl -s --cacert /etc/ssl/litellm/litellm.crt "https://$H/key/generate" \
-H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' -d '{"models":[]}'; echo{"error":{"message":"{'error': 'DB not connected. See https://docs.litellm.ai/docs/proxy/virtual_keys'}","type":"internal_server_error","param":"None","code":"500"}}To turn these features on, point LiteLLM at a PostgreSQL database that you control, such as an Amazon RDS for PostgreSQL instance in the same VPC. Keep the database private to the VPC. Add the connection string to the secrets file, and follow the LiteLLM virtual keys documentation for the database client setup:
sudo nano /etc/litellm/litellm-secrets.env
# add: DATABASE_URL=postgresql://litellm:<db-password>@<rds-endpoint>:5432/litellm
sudo systemctl restart litellm.serviceThe UI then signs in as admin with LITELLM_UI_PASSWORD from your credentials file. Do not change LITELLM_SALT_KEY once the database holds provider credentials, because LiteLLM encrypts them with it.
Serve LiteLLM under your own DNS name
Port 80 redirects to HTTPS on the configured hostname, and the certificate covers that name, the instance's public and private addresses, localhost and 127.0.0.1:
H=$(sudo grep '^LITELLM_HOST=' /root/litellm-credentials.txt | cut -d= -f2-)
curl -s -o /dev/null -w '%{http_code} %{redirect_url}\n' "http://$H/v1/models" openssl x509 -in /etc/ssl/litellm/litellm.crt -noout -subject -enddate -ext subjectAltName301 https://ec2-3-84-115-65.compute-1.amazonaws.com/v1/models subject=CN = ec2-3-84-115-65.compute-1.amazonaws.com, O = sac notAfter=Jan 21 11:37:14 2029 GMT X509v3 Subject Alternative Name: DNS:ec2-3-84-115-65.compute-1.amazonaws.com, IP Address:3.84.115.65, IP Address:172.31.85.155, DNS:ip-172-31-85-155.ec2.internal, IP Address:127.0.0.1, DNS:localhostTo use your own name, point a DNS record at the instance. An Elastic IP keeps the address stable across stops. Then run the helper. It records the name in /etc/sac/litellm-hostname, issues a new self-signed certificate for it, updates the credentials file and reloads nginx:
sudo litellm-set-hostname <your-dns-name>For a publicly trusted certificate, put the instance behind an Application Load Balancer with an AWS Certificate Manager certificate, or replace /etc/ssl/litellm/litellm.crt and litellm.key with your own and run sudo systemctl reload nginx.
Check the security controls
These checks confirm that the LiteLLM service carries the metadata block, and that nginx refuses cross-origin writes and requests for any hostname it was not configured with:
systemctl show -p IPAddressDeny litellm.service
H=$(sudo grep '^LITELLM_HOST=' /root/litellm-credentials.txt | cut -d= -f2-)
curl -s -o /dev/null -w 'cross-origin POST: %{http_code}\n' --cacert /etc/ssl/litellm/litellm.crt \
-X POST -H 'Origin: https://evil.example' "https://$H/key/generate" code=$(curl -s -o /dev/null -w '%{http_code}' -H 'Host: evil.example' http://127.0.0.1/ || true); echo "unknown Host: ${code} (connection closed by nginx)"IPAddressDeny=169.254.169.254/32 168.63.129.16/32 fd00:ec2::254/128 cross-origin POST: 403 unknown Host: 000 (connection closed by nginx)Maintenance
- Logs: run
sudo journalctl -u litellm.service -ffor the gateway. HTTPS access logs are in/var/log/nginx/. - Configuration changes: edit
/etc/litellm/config.yamlor the secrets file, then runsudo systemctl restart litellm.service. - Operating system updates: Ubuntu's unattended security upgrades stay on. Apply the rest with
sudo apt update && sudo apt upgradein a maintenance window. - Upgrading LiteLLM: upgrade inside the virtual environment, remove
litellm-enterpriseagain if you do not hold a BerriAI Enterprise licence, and restart:
sudo /opt/litellm/venv/bin/pip install --upgrade 'litellm[proxy]'
sudo /opt/litellm/venv/bin/pip uninstall -y litellm-enterprise
sudo systemctl restart litellm.service- Backups:
/etc/litellm/holds the whole configuration (config.yamland the root-only secrets file). Keep a copy somewhere safe. An AMI or EBS snapshot of the instance also captures it.
Support
SecureAnyCloud provides 24/7 support for this image by email and live chat. We can help with launching and connecting, provider configuration, TLS and hostnames, and upgrades.
Trademarks
LiteLLM is developed by BerriAI, Inc. Ubuntu is a registered trademark of Canonical Ltd. All other product and company names are trademarks or registered trademarks of their respective holders. SecureAnyCloud is not affiliated with or endorsed by them.
Deploy on AWS
Launch LiteLLM 1.88.0 on Ubuntu 24.04 on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com