Artificial Intelligence (AI) Azure

Cognee on Ubuntu 24.04 on Azure User Guide

| Product: Cognee on Ubuntu 24.04 LTS on Azure

Overview

This guide covers the deployment and configuration of Cognee on Ubuntu 24.04 on Azure using cloudimg Azure Marketplace images. Cognee is an open source AI memory engine. You give it documents, notes, transcripts or web pages; it uses a language model to extract the people, organisations, products, places and events in them and the relationships between them into a knowledge graph, while embedding the same text into a vector store. Questions are then answered from the graph and the vectors together, with the supporting evidence, so an answer can follow how facts connect across your sources.

A web interface lets you add data to "brains" (datasets), explore the extracted graph as a mind map and ask questions. Everything is also available over a documented REST API with per user API keys, so agents and applications can use Cognee as long term memory.

The cloudimg image ships Cognee v1.6.4 under the Apache 2.0 licence and works with no API key on arrival: a local open source language model (Qwen2.5 7B Instruct, Apache 2.0) is served by Ollama on the CPU, and a local embedding model computes the vectors, so your data never leaves the VM unless you choose a hosted provider. Storage is embedded (SQLite, LanceDB and an embedded graph database), so there is no database server to run or secure. Backed by 24/7 cloudimg support.

Cognee is an independent open source project by Topoteretes. This image is produced by cloudimg and is not affiliated with, endorsed by, or sponsored by Topoteretes or the Cognee project. It ships the free and open source Apache 2.0 licensed software, built from the upstream source.

All seven units active, and only ports 22, 80 and 443 reachable from the network

What is included:

  • Cognee v1.6.4 backend, installed from the upstream release tag with every Python dependency checked against the upstream lock file hashes
  • The Cognee web interface, built from the Apache 2.0 source in the same release, not a floating prebuilt image
  • Ollama v0.40.5 (MIT) with the CPU backend only, serving Qwen2.5 7B Instruct (Apache 2.0) pinned by SHA-256 digest
  • A local embedding model (BAAI bge small en v1.5, MIT) and its tokenizer, pinned by SHA-256 and cached in the image, so first boot downloads nothing
  • nginx on port 443 with a TLS certificate generated for each VM; port 80 only redirects to HTTPS
  • Authentication enforced, a unique 24 character admin password and unique token signing secrets generated on first boot, and the old default password proven to be refused before anything is served
  • The API, the web interface and the model server listening on 127.0.0.1 only
  • The application, its interface and the model server blocked from reaching the Azure instance metadata service and the platform wire server
  • Dependency licence inventories shipped at /usr/share/cognee/
  • Ubuntu 24.04 LTS with the latest security patches at build time and unattended security upgrades enabled
  • 24/7 cloudimg support with guaranteed 24 hour response SLA

Prerequisites

  • Active Azure subscription, an SSH public key, and a VNet and subnet in your target region
  • A subscription to the Cognee listing on Azure Marketplace
  • Recommended size Standard_B4ms (4 vCPU, 16 GiB). The bundled 7B model needs about 5 GiB of memory while it is loaded.

Be realistic about the bundled CPU model. It is there so the appliance is useful, private and free of API keys from the first minute, not to be fast. Measured on Standard_B4ms: building the memory for a three sentence document took about 7 minutes, and answering a question about it took about 90 seconds. Time grows with the amount of text. B-series VMs are burstable, so long ingestion runs can exhaust CPU credits and slow down further. For production volumes, either switch Cognee to a hosted model provider (Step 11; processing then takes seconds) or run on a larger non-burstable size such as Standard_D8s_v5. No GPU is required.

Step 1: Deploy from the Azure Portal

  1. In the Azure Portal, search the Marketplace for Cognee by cloudimg and select Create.
  2. Choose your subscription, resource group and region, and set the VM name.
  3. Select size Standard_B4ms, authentication type SSH public key, and paste your key.
  4. Under Inbound port rules, allow SSH (22) and HTTPS (443). Port 80 is optional; it only redirects to HTTPS. Restrict the source of 443 to your own network (see Security hardening).
  5. Leave the OS disk defaults, then Review + create.

First boot takes about two minutes. It generates this VM's secrets and certificate, starts the services on the loopback address, proves that authentication is enforced, and only then opens nginx. If anything in that sequence fails, nothing is left listening.

Step 2: Deploy from the Azure CLI

Replace the placeholder values with your own. This block is illustrative and is not executed by the walk through.

az vm image terms accept --urn cloudimg1647283583153:cognee-ubuntu-24-04:default:latest
az vm create \
  --resource-group my-resource-group \
  --name my-cognee-vm \
  --image cloudimg1647283583153:cognee-ubuntu-24-04:default:latest \
  --size Standard_B4ms \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_rsa.pub \
  --public-ip-sku Standard \
  --os-disk-delete-option Delete --nic-delete-option Delete

Then allow HTTPS from your own network only:

az network nsg rule create \
  --resource-group my-resource-group \
  --nsg-name my-cognee-vmNSG \
  --name allow-https-from-office \
  --priority 1010 --access Allow --protocol Tcp \
  --destination-port-ranges 443 --source-address-prefixes 203.0.113.0/24

Step 3: Connect to your VM

ssh azureuser@<vm-ip>

Step 4: Confirm the services are running

Seven units make up the appliance: cognee-netguard (firewall rules for the services), cognee-firstboot (per VM secrets and the authentication proof), ollama (the local model server, in its own private network namespace), ollama-proxy.socket (the only door into it), cognee (the API), cognee-ui (the web interface) and nginx (HTTPS).

systemctl is-active cognee-netguard cognee-firstboot ollama ollama-proxy.socket cognee cognee-ui nginx

Expected output:

active
active
active
active
active
active
active

Step 5: Read 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/cognee-credentials.txt

Expected output (your address and password will differ):

# cognee — per-VM credentials (generated at first boot on 2026-10-16T02:14:19Z)
COGNEE_URL=https://20.42.14.78/
COGNEE_ADMIN_EMAIL=default_user@example.com
COGNEE_ADMIN_PASSWORD=<unique per VM>
COGNEE_LLM=bundled local model (Ollama, qwen2.5:7b-instruct-q4_K_M) — see the guide to switch to your own provider key

The sign in name is Cognee's own default account name, default_user@example.com. Its password is unique to this VM; the upstream default password default_password does not work and first boot proves that before nginx opens.

The per VM credentials file (password redacted here) with the default password and an anonymous call both refused

Step 6: Open the web interface

Browse to https://<vm-ip>/. The certificate is self signed and unique to this VM, so your browser shows a warning the first time. To confirm you are talking to your own VM, compare the fingerprint your browser shows with the one on the VM:

openssl x509 -in /etc/ssl/certs/cognee-vm.crt -noout -fingerprint -sha256

Sign in with default_user@example.com and the password from Step 5. The sign in form is pre filled with Cognee's default password; replace it with yours.

The Cognee sign in page

After signing in you land on the overview. Panels that say "Cognee Cloud feature" link to the upstream project's separate hosted service; they are not part of this image and nothing on the VM contacts it.

The overview and navigation after signing in

Brain is where datasets live. Use New brain to create one and upload documents into it (text, Markdown, PDF and more). Cognee then builds the knowledge graph for it in the background.

A brain holding one ingested document

Search answers questions from a brain's graph and shows the evidence it used. Choose the brain with the selector above the question box.

A question answered from the knowledge graph, with the supporting evidence

Mindmap draws the extracted entities and their connections.

The knowledge graph Cognee built from the document

Step 7: Check the security posture

The image ships a read only self check. Each probe is paired with a control so that a pass means something: for example, the metadata service test first proves that root can reach it, then proves the application users cannot.

sudo cognee-selfcheck

Expected output:

PASS  network listeners are exactly 22 80 443
PASS  port 8000 bound to 127.0.0.1 only
PASS  port 3000 bound to 127.0.0.1 only
PASS  port 11434 bound to 127.0.0.1 only
PASS  port 11435 bound to 127.0.0.1 only
PASS  loopback listeners are exactly the UI, API, model gateway and model server (3000 8000 11434 11435)
PASS  port 80 only redirects to HTTPS (301)
PASS  anonymous API call refused (401)
PASS  upstream default password refused (400)
PASS  public self registration closed (403)
PASS  cognee (inside cognee.service) cannot reach IMDS or the WireServer
PASS  cognee-ui (inside cognee-ui.service) cannot reach IMDS or the WireServer
PASS  ollama (inside ollama.service) cannot reach IMDS or the WireServer
PASS  control: root reaches IMDS (200), so the blocks above are real
PASS  model server: gateway needs this VM's key (cognee w/o key 401), raw Ollama unreachable (cognee 000, nobody 000/000)
PASS  cognee app cannot reach loopback API/UI/TLS or private networks (control: root reaches the API, 200)
SELFCHECK OK

The self check: listeners, anonymous refusal, closed registration, metadata service blocked and the model server answering the app only

What the image enforces, and why:

Control Detail
Authentication REQUIRE_AUTHENTICATION=true with Cognee's multi user access control on. Every API route except /health refuses anonymous callers.
No default password Cognee 1.6 creates its default account without a password unless one is configured. First boot sets a unique one, proves it signs in and that default_password is refused, then removes it from the configuration file.
HTTPS only nginx terminates TLS with a per VM certificate; port 80 only redirects. Session cookies are forced to Secure and HttpOnly.
Closed registration Public sign up, password reset and e mail verification are closed at nginx (there is no mail server). Administrators add users from the VM itself (Step 12).
Loopback only The API (8000), web interface (3000) and model gateway (11434) listen on 127.0.0.1 only.
Server side request forgery Cognee fetches URLs you give it. At the network layer the cognee service account cannot reach the instance metadata service (169.254.169.254), the wire server (168.63.129.16), private, shared or link local networks, or anything on the loopback interface except the DNS resolver and the key gated model gateway, so not the API, the web interface or the raw model server either. This is enforced by nftables per user and by systemd per service, independently of Cognee's own URL checks, so a hostname that resolves to an internal address or a redirect to one is refused too.
Model server isolated Ollama has no authentication of its own, so it runs in a private network namespace behind 127.0.0.1:11435, which only the gateway may open. The gateway on 127.0.0.1:11434 only passes requests that carry this VM's random LLM_API_KEY, and only the cognee service account (and root) may connect to it.
Fail closed The services refuse to start until first boot has written this VM's secrets, and nginx refuses to start until first boot has proven authentication.

Step 8: Sign in to the API

Everything in the interface is available over the REST API. Sign in once and keep the token in a file only you can read. The password is read straight from the credentials file and passed on standard input, so it never appears in a command line.

sudo sed -n 's/^COGNEE_ADMIN_PASSWORD=//p' /root/cognee-credentials.txt | tr -d '\n' \
  | curl -s --cacert /etc/ssl/certs/cognee-vm.crt https://127.0.0.1/api/v1/auth/login \
      --data-urlencode "username=default_user@example.com" --data-urlencode "password@-" \
  | python3 -c 'import json,sys; print(json.load(sys.stdin)["access_token"])' > ~/.cognee-token
chmod 600 ~/.cognee-token
curl -s --cacert /etc/ssl/certs/cognee-vm.crt -H "Authorization: Bearer $(cat ~/.cognee-token)" \
  https://127.0.0.1/api/v1/users/me | python3 -c 'import json,sys; print(json.load(sys.stdin)["email"])'

Expected output:

default_user@example.com

Without a token the same call is refused:

curl -s -o /dev/null -w '%{http_code}\n' --cacert /etc/ssl/certs/cognee-vm.crt https://127.0.0.1/api/v1/users/me

Expected output:

401

For scripts and agents, create a long lived key on the API Keys page and send it as the X-Api-Key header instead of a bearer token.

Step 9: Add a document

cat > /tmp/northwind.txt <<'DOC'
Northwind Analytics is a data consultancy founded in 2019 by Priya Raman in Leeds.
Its flagship product is Lighthouse, a forecasting tool used by the Harbour Rail company.
In 2024 Northwind opened a second office in Bristol, led by Tomas Ferreira.
DOC
curl -s --cacert /etc/ssl/certs/cognee-vm.crt -H "Authorization: Bearer $(cat ~/.cognee-token)" \
  -F "datasetName=quickstart" -F "data=@/tmp/northwind.txt" \
  https://127.0.0.1/api/v1/add | python3 -c 'import json,sys; print(json.load(sys.stdin)["status"])'

Expected output:

PipelineRunCompleted

Step 10: Build the memory, then ask a question

cognify reads the document with the language model and builds the graph. With the bundled CPU model this takes several minutes, so start it in the background:

curl -s --cacert /etc/ssl/certs/cognee-vm.crt -H "Authorization: Bearer $(cat ~/.cognee-token)" \
  -H 'Content-Type: application/json' -d '{"datasets":["quickstart"],"run_in_background":true}' \
  https://127.0.0.1/api/v1/cognify | python3 -c 'import json,sys; d=json.load(sys.stdin); print(sorted({v["status"] for v in d.values()}))'

Expected output:

['PipelineRunStarted']

Check progress at any time:

curl -s --cacert /etc/ssl/certs/cognee-vm.crt -H "Authorization: Bearer $(cat ~/.cognee-token)" \
  https://127.0.0.1/api/v1/datasets/status

The value is DATASET_PROCESSING_STARTED while the graph is being built and DATASET_PROCESSING_COMPLETED when it is ready. Once it is complete, ask a question (this waits for completion first; answering takes around a minute and a half on the bundled CPU model):

# ask-after-cognify
H="Authorization: Bearer $(cat ~/.cognee-token)"
for i in $(seq 1 12); do
  curl -s --cacert /etc/ssl/certs/cognee-vm.crt -H "$H" https://127.0.0.1/api/v1/datasets/status \
    | python3 -c 'import json,sys; d=json.load(sys.stdin); sys.exit(0 if d and all("COMPLETED" in v for v in d.values()) else 1)' && break
  sleep 5
done
curl -s --cacert /etc/ssl/certs/cognee-vm.crt -H "$H" -H 'Content-Type: application/json' \
  -d '{"query":"Who founded Northwind Analytics, and in which city?","datasets":["quickstart"]}' \
  https://127.0.0.1/api/v1/search | python3 -c 'import json,sys; print(json.load(sys.stdin)[0]["search_result"][0])'

Expected output:

Priya Raman founded Northwind Analytics in Leeds.

Step 11: Switch to your own model provider (optional)

The bundled model keeps everything on the VM. For faster processing and stronger answers, point Cognee at a hosted provider by editing /etc/cognee/cognee.env (readable by root only) and replacing the four LLM_ lines. Keep the local embedding settings unchanged: changing the embedding model on a dataset that already has vectors requires rebuilding it.

OpenAI:

LLM_PROVIDER=openai
LLM_MODEL=openai/gpt-4o-mini
LLM_ENDPOINT=
LLM_API_KEY=sk-your-openai-key

Azure OpenAI (API key; managed identity is not available because the application is deliberately blocked from the instance metadata service):

LLM_PROVIDER=azure
LLM_MODEL=azure/your-deployment-name
LLM_ENDPOINT=https://your-resource.openai.azure.com
LLM_API_KEY=your-azure-openai-key
LLM_API_VERSION=2024-12-01-preview

If your provider endpoint has a private address on your own network (an Azure OpenAI private endpoint, or a model server on another VM), allow that address first, because the application is blocked from private networks by default. Add it to the cognee_private_allow set in /etc/cognee/netguard.nft (for example elements = { 10.1.2.3 }), and add a matching IPAddressAllow=10.1.2.3 with sudo systemctl edit cognee, then run sudo systemctl restart cognee-netguard.

Then restart the API:

sudo systemctl restart cognee

Once you no longer use the local model you can stop it to free memory with sudo systemctl disable --now ollama-proxy.socket ollama.

Step 12: Add users

Public self registration is closed. Create additional accounts from the VM itself, where the registration endpoint is still reachable on the loopback address:

curl -s -X POST http://127.0.0.1:8000/api/v1/auth/register \
  -H 'Content-Type: application/json' \
  -d '{"email":"analyst@example.com","password":"<new-password>"}'

With multi user access control on, each user sees only their own brains unless access is shared.

Step 13: Back up and restore

All of Cognee's data (accounts, documents, graph, vectors) lives under /var/lib/cognee. Stop the API for a consistent copy:

sudo systemctl stop cognee cognee-ui
sudo tar czf /var/backups/cognee-backup.tar.gz -C /var/lib cognee
sudo systemctl start cognee cognee-ui
ls -l /var/backups/cognee-backup.tar.gz | awk '{print $1, $3, $9}'

Expected output:

-rw-r--r-- root /var/backups/cognee-backup.tar.gz

Copy the archive off the VM, for example to Azure Blob Storage. To restore, stop the services, replace /var/lib/cognee with the archive contents (owned by cognee), and start them again.

Step 14: Logs and day to day operation

sudo journalctl -u cognee -n 20 --no-pager

Useful commands:

Task Command
Restart the API sudo systemctl restart cognee
Restart the web interface sudo systemctl restart cognee-ui
Model server logs sudo journalctl -u ollama -n 50
First boot log sudo journalctl -u cognee-firstboot
Re check security sudo cognee-selfcheck

Exactly what is installed, and where it came from:

cat /usr/share/cognee/PROVENANCE

Pinned versions, model digest and the dependency licence scan results

Security hardening

  • Restrict the source of port 443 in your network security group to the networks that need it, and close port 22 to everything except your management network.
  • Replace the self signed certificate with your own: put the certificate and key at /etc/cognee/tls/cognee.crt and /etc/cognee/tls/cognee.key (and a copy of the certificate at /etc/ssl/certs/cognee-vm.crt) and run sudo systemctl reload nginx.
  • Change the admin password from the interface after first sign in, and create a separate account for each person (Step 12).
  • Security updates for Ubuntu are installed automatically by unattended upgrades.

Troubleshooting

  • Search says no data or returns nothing: the brain's graph is not built yet. Check /api/v1/datasets/status (Step 10) and wait for DATASET_PROCESSING_COMPLETED.
  • Processing is very slow: expected with the bundled CPU model. See the measurements under Prerequisites, and Step 11 to switch to a hosted provider.
  • The browser shows a certificate warning: expected with the per VM self signed certificate; compare the fingerprint (Step 6) or install your own certificate.
  • Nothing answers on 443 after deployment: first boot may still be running; check sudo journalctl -u cognee-firstboot. If first boot failed it stops every service on purpose.

Support

cloudimg provides 24/7 support for this image with a guaranteed 24 hour response. Contact support@cloudimg.co.uk with your VM's region and the output of sudo cognee-selfcheck.