LightRAG
Overview
This guide covers deploying and configuring LightRAG on Ubuntu 24.04 on Azure, using the SecureAnyCloud Azure Marketplace images. LightRAG is a graph-based retrieval-augmented generation server from the HKU Data Intelligence Lab. You upload documents, and LightRAG uses your chosen language model to extract the entities in them, and the relationships between those entities, into a knowledge graph while it embeds the text into a vector index. Questions are answered from both at once, so answers are grounded in how the facts in your corpus connect rather than in isolated, similar-looking paragraphs.
What you get:
- A bundled web interface to upload and track documents, watch the indexing pipeline, explore the extracted knowledge graph visually, edit entities and relationships by hand, and query in naive, local, global, hybrid or mix retrieval modes. Everything is also available over a documented REST API, and the server speaks the Ollama chat protocol so existing chat clients can point straight at it.
- A front end to your models, not a model host. LightRAG calls an OpenAI-compatible endpoint for generation and an embedding endpoint for indexing, so it runs comfortably on a small CPU-only VM and needs no GPU. Point it at OpenAI, Azure OpenAI, Google Gemini, AWS Bedrock, Anthropic, or a private Ollama, vLLM, LM Studio or TGI server on your own network.
- LightRAG v1.5.4 (the MIT licensed upstream container
ghcr.io/hkuds/lightrag), pinned by image digest, not by a moving tag - Docker Engine and the Compose plugin from the official Docker APT repository
- An nginx access gateway on port
80, installed as a host package so unattended security upgrades keep the internet-facing component patched - File-based storage (
JsonKVStorage,JsonDocStatusStorage,NetworkXStorageandNanoVectorDBStorage), with no database server of any kind on the instance, so there is nothing to secure, patch or licence - A unique 32-character access credential, a unique API key and a unique token signing secret generated per VM on first boot, never baked into the image
- Fail-closed guards: both the application service and the gateway refuse to start unless this VM's own credentials are in place, and the gateway additionally refuses to start until first boot has proved that the gate denies an unauthenticated request with 401
- LightRAG's own account authentication configured (it is optional upstream, and unconfigured it accepts every request), with the path whitelist narrowed so no model-spending route is ever exempt
- Model provider keys shipped empty, so you always supply your own
- A shipped dependency licence inventory at
/usr/share/lightrag/dependency-licences.txt - Ubuntu 24.04 LTS base with the latest security patches applied at build time
- Azure Linux Agent for seamless cloud integration and SSH key injection
- 24/7 SecureAnyCloud support with a guaranteed 24-hour response SLA
LightRAG is an independent open source project. This image is produced by SecureAnyCloud and is not affiliated with, endorsed by, or sponsored by the LightRAG team or the University of Hong Kong. It ships the free and open source MIT licensed software, unmodified.
Prerequisites
- An active Azure subscription, an SSH public key, and a VNet and subnet in the target region.
- A subscription to the LightRAG listing on Azure Marketplace.
- A model provider that LightRAG can reach. LightRAG needs two endpoints from you: a chat/completions endpoint to extract the knowledge graph and write answers, and an embeddings endpoint to build the vector index. The image ships pre-filled for OpenAI with the key left empty, and carries commented examples for Azure OpenAI, Ollama and any OpenAI-compatible server. SecureAnyCloud does not supply a key and never bundles one.
- The recommended size, Standard_B2ms (2 vCPU / 8 GiB). LightRAG holds its knowledge graph and vector index in memory while serving, and both grow with your corpus. 8 GiB is comfortable where 4 GiB is tight. No GPU is required.
Deploy from the Azure Portal
- In the Azure Portal, search the Marketplace for LightRAG by SecureAnyCloud and select Create.
- Choose your subscription, resource group and region, and set the VM name.
- Select size Standard_B2ms and authentication type SSH public key, then paste your key.
- Under Inbound port rules, allow SSH (22) and HTTP (80). Restrict the source of port 80 to your own network, as described in Security hardening below.
- Leave the OS disk defaults, then select Review + create.
Deploy from the Azure CLI
Replace the example values with your own. This block is an example and is not run as part of the walkthrough.
az vm image terms accept --urn sac1647283583153:lightrag-ubuntu-24-04:default:latest
az vm create \
--resource-group my-resource-group \
--name my-lightrag-vm \
--image sac1647283583153:lightrag-ubuntu-24-04:default:latest \
--size Standard_B2ms \
--admin-username azureuser \
--ssh-key-values ~/.ssh/id_rsa.pub \
--public-ip-sku Standard \
--os-disk-delete-option Delete --nic-delete-option DeleteThen open port 80 to your own network only:
az network nsg rule create \
--resource-group my-resource-group \
--nsg-name my-lightrag-vmNSG \
--name allow-http-from-office \
--priority 1010 --access Allow --protocol Tcp \
--destination-port-ranges 80 --source-address-prefixes 203.0.113.0/24Connect to your VM
ssh azureuser@<vm-ip>Confirm the services are running
Four units make up the appliance: docker, lightrag-firstboot (which generates this VM's secrets and proves the gate on the very first boot), lightrag (the application container) and nginx (the access gateway).
sudo systemctl is-active docker.service lightrag-firstboot.service lightrag.service nginx.serviceExpected output:
active active active activeThe application container itself is pinned by digest and published on the loopback address only:
sudo docker compose -f /var/lib/lightrag/docker-compose.yml psConfirm the exact image this VM is running, and that it is the MIT licensed upstream release:
sudo docker image inspect $(sudo docker ps --format '{{.Image}}' | head -1) --format 'licence={{index .Config.Labels "org.opencontainers.image.licenses"}} version={{index .Config.Labels "org.opencontainers.image.version"}} source={{index .Config.Labels "org.opencontainers.image.source"}}'Expected output:
licence=MIT version=v1.5.4 source=https://github.com/HKUDS/LightRAGThe licences of every Python dependency inside that image were scanned at build time, and the inventory ships with the appliance:
sudo head -n 3 /usr/share/lightrag/dependency-licences.txtRead the per-instance credentials
Every VM generates its own credentials on first boot. Nothing is shared between instances and nothing is baked into the image.
sudo cat /root/lightrag-credentials.txtThe file gives you three values:
- LIGHTRAG_USERNAME: the account name for both the gateway and LightRAG's own sign-in.
- LIGHTRAG_PASSWORD: the 32-character password for both.
- LIGHTRAG_APIKEY: a 32-character key for scripts. Sent as the X-API-Key header, it satisfies both layers in one header.
Open the web interface
Browse to http://<vm-ip>/.
Your browser asks for a username and password first. This is the gateway, and it stops anyone who finds the address from spending your model provider credit. Enter the username and password from Step 5. The gateway then sets a cookie, so it asks only once.
LightRAG's own sign-in page appears next. Enter the same username and password.
After you sign in, you land on Document Management, which lists everything you have ingested and its indexing status.
Understand the two-layer access model
LightRAG's own account authentication is optional upstream, and it fails open: with no accounts configured, the server accepts every request. Its default path whitelist also exempts /api/generate and /api/chat, the two routes that actually spend your model provider credit. This image closes both gaps.
Layer one: the gateway. nginx owns port 80 and denies by default. It accepts a request only if the request carries this VM's gate cookie, this VM's API key or this VM's HTTP Basic credential. Prove that it refuses an anonymous caller:
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1/Expected output:
401The gateway refuses the routes that would spend your credit in the same way:
curl -s -o /dev/null -w '%{http_code}\n' -X POST -H 'Content-Type: application/json' -d '{}' http://127.0.0.1/api/chatExpected output:
401A wrong password is refused too, not only a missing one:
curl -s -o /dev/null -w '%{http_code}\n' -u '<LIGHTRAG_USERNAME>:definitely-not-the-password' http://127.0.0.1/Expected output:
401Layer two: LightRAG's own accounts. Getting past the gateway is not enough. An application route still needs an application credential:
curl -s -o /dev/null -w '%{http_code}\n' -u '<LIGHTRAG_USERNAME>:<LIGHTRAG_PASSWORD>' http://127.0.0.1/documents/pipeline_statusExpected output:
401The API key satisfies both layers in a single header, so use it from scripts:
curl -s -H 'X-API-Key: <LIGHTRAG_APIKEY>' http://127.0.0.1/graph/label/listThe gateway cannot run ungated. nginx.service carries two ConditionPathExists directives: this VM's credential file, and a marker that first boot writes only after it has proved, against a throwaway internal listener, that the gate answers an unauthenticated request with 401. If that proof fails, first boot tears the stack down and deletes both files, so nginx can never start. Show both conditions:
sudo systemctl cat nginx.service | grep ConditionPathExistsThe application is never reachable directly. It is published on the loopback address only, so every request must pass the gateway:
sudo ss -lntH | awk '{print $4}' | sort -uAdd your own model provider
LightRAG does not host a model. Until you give it a provider, it can serve the interface but cannot index a document or answer a question.
The configuration file is /var/lib/lightrag/lightrag.env. It ships pre-filled for OpenAI with both keys empty:
sudo grep -E '^(LLM_BINDING|LLM_MODEL|EMBEDDING_BINDING|EMBEDDING_MODEL|EMBEDDING_DIM)=' /var/lib/lightrag/lightrag.envEdit the file and set your own keys. You perform this step yourself; it is not run as part of the walkthrough:
sudo nano /var/lib/lightrag/lightrag.envSet LLM_BINDING_API_KEY= and EMBEDDING_BINDING_API_KEY= to your own key, then restart and wait for the service to come back:
sudo systemctl restart lightrag.service for i in $(seq 1 30); do [ "$(curl -s -o /dev/null -w '%{http_code}' --max-time 5 -H 'X-API-Key: <LIGHTRAG_APIKEY>' http://127.0.0.1/health)" = "200" ] && break sleep 2 done
sudo systemctl is-active lightrag.serviceThe file carries commented blocks for the common alternatives:
- Azure OpenAI. Set
LLM_BINDING=azure_openaiandLLM_BINDING_HOST=https://<your-resource>.openai.azure.com/, and use your deployment names forLLM_MODELandEMBEDDING_MODEL. - Ollama on this VM or your network. Set
LLM_BINDING=ollamaandLLM_BINDING_HOST=http://host.docker.internal:11434. The container is already configured to reach the VM's own host address. - Any OpenAI-compatible server (vLLM, LM Studio, TGI, OpenRouter, Together). Keep
LLM_BINDING=openaiand pointLLM_BINDING_HOSTat its/v1URL.
Your key stays on this VM. SecureAnyCloud never ships a model provider credential, and the image is built and tested with both key fields empty.
Ingest a document and query it
Upload through the web interface with Documents > Upload, or over the API. Indexing is asynchronous. LightRAG chunks the document, asks your model to extract entities and relationships, embeds the passages and merges the result into the knowledge graph.
Watch the pipeline:
curl -s -H 'X-API-Key: <LIGHTRAG_APIKEY>' http://127.0.0.1/documents/pipeline_status | head -c 300List the entities currently in the knowledge graph:
curl -s -H 'X-API-Key: <LIGHTRAG_APIKEY>' http://127.0.0.1/graph/label/listThe Knowledge Graph tab draws what was extracted. Entities are nodes, and the relationships your model found between them are edges. Click any node to inspect or edit its description.
Ask a question from the Retrieval tab, or over the API. The mode setting selects how much of the graph is used: naive is plain vector search, local and global walk the graph from different directions, hybrid combines them and mix uses everything.
LightRAG refuses to ingest the same file name twice. To re-index a changed document, delete the existing record first.
Where your data lives
Storage is file-based by design. There is no database server on this instance, so there is nothing extra to secure, patch or licence.
sudo ls -la /var/lib/lightrag/data/rag_storage/- graph_*.graphml: the entity and relationship graph, stored with NetworkX (BSD-3-Clause).
- vdb_*.json: the vector indexes for entities, relations and chunks, stored with NanoVectorDB (MIT).
- kv_store_*.json: documents, chunk text and indexing status, stored in the JSON key/value store.
Your uploaded originals live alongside them in /var/lib/lightrag/data/inputs. Both directories are 0700 root:root. The gateway serves no file from disk at all and only proxies to the application, so nothing you ingest is reachable over HTTP except through LightRAG's own authenticated API.
sudo stat -c '%n %a %U:%G' /var/lib/lightrag/data /var/lib/lightrag/data/inputs /var/lib/lightrag/data/rag_storageExpected output:
/var/lib/lightrag/data 700 root:root /var/lib/lightrag/data/inputs 700 root:root /var/lib/lightrag/data/rag_storage 700 root:rootBack up that one directory to back up your entire knowledge base:
sudo tar czf /var/backups/lightrag-kb-$(date +%Y%m%d).tar.gz -C /var/lib/lightrag dataDay-to-day operation
sudo systemctl restart lightrag.servicesudo docker compose -f /var/lib/lightrag/docker-compose.yml logs --tail 20Configuration changes always need a service restart, because the file is mounted read-only into the container.
Security hardening
- Restrict port 80 in the network security group to the networks that need it. The gateway is strong, but there is no reason to expose it to the whole internet.
- Put TLS in front before exposing the instance beyond your own network. Terminate TLS on an Azure Application Gateway, an Azure Front Door or a reverse proxy of your own, and forward to port 80 on this VM.
- The gate cookie is deliberately not marked
Secure. By default the appliance is reached overhttp://on a VM IP, and browsers refuse to store aSecurecookie over plain HTTP. Once you have TLS in front, you can add that attribute yourself. - Rotate the credentials by editing
/etc/nginx/lightrag.htpasswd(withhtpasswd -B), the matching entries in/etc/nginx/conf.d/lightrag-gate-map.conf, andAUTH_ACCOUNTS/LIGHTRAG_API_KEYin/var/lib/lightrag/lightrag.env. - Do not widen
WHITELIST_PATHS. It is deliberately narrowed to/health. LightRAG's upstream default also exempts/api/*, which would leave the model-spending routes unauthenticated. - Unattended security upgrades are enabled and keep the gateway and the base OS patched.
Troubleshooting
The web interface asks for a password twice. This is expected. The gateway asks once, then LightRAG's own sign-in asks once. Both take the same username and password, and the gateway's cookie stops it from asking again.
Indexing never completes. LightRAG needs a working model provider. Check the container log for provider errors:
sudo docker compose -f /var/lib/lightrag/docker-compose.yml logs --tail 30Confirm that your keys are set and that the endpoint is reachable from the VM. An empty LLM_BINDING_API_KEY is the shipped state and fails every extraction.
The gateway will not start. It is fail-closed by design. Check the guard's own reason:
sudo /usr/local/sbin/lightrag-preflight.sh --nginx || trueA query returns "no context". Nothing in the knowledge base matched. Confirm that a document finished indexing (Completed in the Documents tab) and that entities exist at /graph/label/list.
Support
SecureAnyCloud provides 24/7 support with a guaranteed 24-hour response SLA for this image. Contact support through the Azure Marketplace listing.
LightRAG itself is an independent open source project licensed under the MIT licence. Raise questions about the software's own behaviour with the upstream project. Questions about the image, its packaging, its security model or its operation on Azure are ours to answer.
Deploy on Azure
Launch LightRAG on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com