DocsGPT on Ubuntu 24.04 on Azure User Guide
Overview
This guide covers the deployment and operation of DocsGPT on Ubuntu 24.04 on Azure using cloudimg Azure Marketplace images. DocsGPT is an open source, MIT licensed assistant that answers questions from your own content (retrieval augmented generation, or RAG). You upload documents or point it at a website, DocsGPT splits and indexes them, and when you ask a question it finds the relevant passages and writes an answer that cites the sources it used.
The image runs the whole stack on one VM:
- DocsGPT serves the web interface and the REST API, and a worker ingests and indexes your documents. Both run from the official DocsGPT 1.0.0 container image
- PostgreSQL stores conversations, sources and settings, and Valkey (the open source Redis fork) carries the job queue and cache
- An embedding model (IBM Granite Embedding 311M, multilingual) runs on the VM's CPU and turns your documents into vectors, so nothing is sent anywhere to index them
- Ollama serves a small local language model, Qwen2.5 1.5B Instruct, on the VM's CPU. It is already DocsGPT's default model, so you can ask questions the moment you sign in, with no API key
- nginx terminates HTTPS with a certificate generated for this VM and asks for this VM's password on every page and API call
| Component | Version | Licence |
|---|---|---|
| DocsGPT (API, web UI, worker) | 1.0.0 | MIT |
| Embedding models (bundled in the DocsGPT image) | Granite Embedding 311M multilingual R2, all-mpnet-base-v2 | Apache 2.0 |
| PostgreSQL | 16.15 | PostgreSQL Licence |
| Valkey | 9.1.2 | BSD 3-Clause |
| Ollama (CPU) | 0.40.5 | MIT |
Qwen2.5 1.5B Instruct (qwen2.5:1.5b, Q4_K_M) |
Ollama manifest f2b0a490 |
Apache 2.0 |
| Docker Engine | 29.9.1 | Apache 2.0 |
Your documents stay on this VM. Upstream DocsGPT sends questions and document passages to Arc53's hosted model by default, checks for updates with an instance identifier, and uses Google for text to speech. In this image all of that is switched off: the bundled local model answers, the version check and speech services are off, and the ONNX runtime's telemetry and Hugging Face downloads are disabled. While building the image we watched the network during a full upload and question: no request left the VM. If you want a cloud model, you connect it deliberately (Step 10).
About the local model. Qwen2.5 1.5B is small enough to run on a CPU, which is what makes this image work out of the box, but it is a small model. On the recommended Standard_D4s_v4 a typical question about your documents is answered in about 10 to 15 seconds (measured: 8 to 14 seconds for a question that pulled in six passages), and in about 20 to 30 seconds on a Standard_B4ms; longer questions and larger passages take longer, it answers one question at a time, and it can misread negations or questions that need several steps of reasoning. Always check important answers against the cited sources. For faster and stronger answers, connect a cloud model such as Azure OpenAI or OpenAI (Step 10).
No password, key or certificate is baked into the image. First boot generates, for this VM only, the sign in password, the PostgreSQL and Valkey passwords, DocsGPT's signing, encryption and internal keys, the key DocsGPT uses to reach the local model, and the TLS certificate. Nothing answers on the network until first boot has done this. Backed by 24/7 cloudimg support.
DocsGPT is developed by Arc53 under the MIT licence. Ollama is developed by Ollama Inc. under the MIT licence, Qwen2.5 by the Qwen team at Alibaba Cloud under the Apache 2.0 licence, and the Granite embedding model by IBM under the Apache 2.0 licence. This image is produced by cloudimg and is not affiliated with, endorsed by, or sponsored by Arc53, the DocsGPT project, Ollama, Alibaba Cloud or IBM. The names are used here solely to identify the software this image contains.

What is included:
- DocsGPT 1.0.0 from the official image, pinned by its SHA-256 digest, with the API and web UI published on
127.0.0.1:7091only - PostgreSQL 16 and Valkey 9 on a private Docker network only, each protected by a per-VM password
- Ollama with Qwen2.5 1.5B Instruct already downloaded, verified and kept loaded in memory. Ollama listens on the VM's loopback address; DocsGPT reaches it through a small model gateway that requires a per-VM key and that only the DocsGPT containers can reach
- nginx terminating HTTPS on
443with a per-VM certificate and password, and redirecting80to HTTPS - A firewall that stops the DocsGPT containers from reaching the Azure Instance Metadata Service, the Azure wire server, your private network and the VM itself, so a crafted URL cannot be used to read the VM's identity or to probe your network
- Unattended security upgrades left on for the operating system
Prerequisites
- An Azure subscription with permission to create VMs
- A
Standard_D4s_v4VM (4 vCPU, 16 GiB) or larger is recommended. DocsGPT, its database and the loaded model use about 4 GiB of memory, and both indexing and answering use all the CPU they can get - About burstable sizes: a
Standard_B4msruns this image well for trying it out and for light use, but it is a burstable size. In our measurements a new B4ms started with about 120 CPU credits, indexing 77 documents used about 19 of them, and sustained work uses about 3 credits a minute more than the VM earns. A first import of a few hundred documents can therefore use up the credits, after which the VM runs at 22.5% of each vCPU and answers become very slow. Choose a non-burstable size such asStandard_D4s_v4for real use - Inbound TCP
443(and80for the redirect) open only to the networks you connect from, plus22for SSH administration - An SSH key pair for administrative access
- Optional: an API key for a cloud model (Azure OpenAI, OpenAI, Anthropic, Google Gemini and others) if you want faster, stronger answers than the local model
Step 1: Deploy from the Azure Portal
- In the Azure Portal, search the Marketplace for DocsGPT and select the cloudimg offer, then Create.
- Choose your subscription, resource group and region.
- Set the VM size to Standard_D4s_v4 or larger.
- Under Administrator account, select SSH public key and supply your own key.
- Under Inbound port rules, allow HTTPS (443), HTTP (80) and SSH (22), then restrict all three to your own address ranges on the networking blade.
- Review and create.
Step 2: Deploy from the Azure CLI
az vm image terms accept --urn cloudimg1647283583153:docsgpt-ubuntu-24-04:default:latest
az vm create \
--resource-group my-resource-group \
--name my-docsgpt \
--image cloudimg1647283583153:docsgpt-ubuntu-24-04:default:latest \
--size Standard_D4s_v4 \
--admin-username azureuser \
--ssh-key-values ~/.ssh/id_rsa.pub \
--public-ip-sku Standard
# Open HTTPS (and the HTTP redirect) to YOUR network only.
MY_CIDR="203.0.113.0/24" # replace with your own range
az network nsg rule create \
--resource-group my-resource-group \
--nsg-name my-docsgptNSG \
--name allow-https-from-office --priority 1010 \
--source-address-prefixes "${MY_CIDR}" \
--destination-port-ranges 80 443 --protocol Tcp --access Allow
Step 3: Connect to your VM
ssh azureuser@<vm-ip>
Step 4: Confirm the services are running
First boot takes about a minute: it generates this VM's secrets and certificate, starts the local model, initialises DocsGPT's database and proves the sign in gate before it finishes.
# Every unit reports "active".
systemctl is-active docker ollama docsgpt docsgpt-model-gateway nginx
test -f /var/lib/cloudimg/docsgpt-firstboot.done && echo "first boot complete"
# Only SSH (22) and nginx (80, 443) listen publicly. DocsGPT listens on 127.0.0.1:7091,
# Ollama on 127.0.0.1:11434, the model gateway on the private Docker bridge address
# 172.30.252.1:11435, and port 53 is the operating system's local DNS resolver.
sudo ss -lntpH | grep -v llama-server | awk '{print $4}' | sort -u
Expected output:
active
active
active
active
active
first boot complete
0.0.0.0:22
0.0.0.0:443
0.0.0.0:80
127.0.0.1:11434
127.0.0.1:7091
127.0.0.53%lo:53
127.0.0.54:53
172.30.252.1:11435
[::]:22
[::]:443
[::]:80
While the model is loaded, Ollama's model runner also listens on a random high port of 127.0.0.1 (the command above hides it); it is loopback only. DocsGPT runs as four containers:
sudo docker compose -f /etc/docsgpt/compose.yaml ps --format 'table {{.Service}}\t{{.State}}\t{{.Ports}}'
SERVICE STATE PORTS
backend running 127.0.0.1:7091->7091/tcp
postgres running 5432/tcp
valkey running 6379/tcp
worker running 7091/tcp
5432/tcp, 6379/tcp and the worker's 7091/tcp are inside the private Docker network. They are not published to the VM or the network.
Step 5: Read this VM's sign in details
Everything in this file was generated on this VM at first boot.
sudo cat /root/docsgpt-credentials.txt
# DocsGPT - per-VM credentials generated on first boot (...). Keep this file private.
# Open DOCSGPT_URL in a browser and sign in with this user name and password.
# Change the password: sudo htpasswd -B /etc/docsgpt/htpasswd admin
DOCSGPT_URL=https://<vm-ip>/
DOCSGPT_USERNAME=admin
DOCSGPT_PASSWORD=<DOCSGPT_PASSWORD>
# Bundled local model (CPU): Qwen2.5 1.5B Instruct via Ollama, already the default model in DocsGPT.
DOCSGPT_MODEL=qwen2.5:1.5b
Step 6: Sign in
- Open
DOCSGPT_URLfrom the credentials file in your browser. The certificate is self-signed and generated for this VM, so your browser warns you the first time. Accept it for this address, or follow Step 12 to use your own domain and a trusted certificate. - Your browser asks for a user name and password: enter
adminandDOCSGPT_PASSWORD. - DocsGPT opens with qwen2.5:1.5b, the local model, already selected.

Change the password from an SSH session (you are asked for the new password twice; it is stored as a bcrypt hash):
sudo htpasswd -B /etc/docsgpt/htpasswd admin
nginx reads the change immediately. The password protects the whole site, so everyone who signs in shares one DocsGPT workspace: give the password only to people who should see every document and conversation (Step 9 explains the access model).
Step 7: Add your documents
- Select Settings, then Knowledge, then Add knowledge.
- Upload files, or choose a website or sitemap to crawl. DocsGPT accepts PDF, Word, Markdown, text, HTML, CSV, Excel, PowerPoint, EPUB and more. It splits each document into chunks and indexes them on the VM's CPU: seconds for a small file, a few minutes for a large set (77 Markdown documents took about 4.5 minutes in our test).
- Select a source to see its chunks, search them, and use Test retrieval to check what a question would find.


You can do the same through the API. Every API call needs this VM's password; keep it in a private curl configuration file rather than on the command line:
PW=$(sudo sed -n 's/^DOCSGPT_PASSWORD=//p' /root/docsgpt-credentials.txt)
( umask 077; printf 'user = "admin:%s"\n' "$PW" > ~/.docsgpt-curl )
curl -sk -K ~/.docsgpt-curl https://127.0.0.1/api/config | jq -c '{auth_type, requires_auth}'
{"auth_type":null,"requires_auth":false}
DocsGPT's own login is off (auth_type null) because nginx already asks for this VM's password on every request; DocsGPT never sees an unauthenticated one. Upload a document and wait for it to be indexed:
cat > ~/harbour-lane-servicing.md <<'EOF'
# Harbour Lane Cycles - Servicing
A standard service costs 65 GBP and takes two working days.
A full overhaul costs 140 GBP and takes five working days.
Every service includes a free safety check after 300 miles.
EOF
TASK=$(curl -sk -K ~/.docsgpt-curl -F user=local -F name=harbour-lane-servicing \
-F file=@"$HOME/harbour-lane-servicing.md" https://127.0.0.1/api/upload | jq -r .task_id)
for i in $(seq 1 60); do
S=$(curl -sk -K ~/.docsgpt-curl "https://127.0.0.1/api/task_status?task_id=$TASK" | jq -r .status)
[ "$S" = SUCCESS ] && break; sleep 3
done
echo "ingest: $S"
curl -sk -K ~/.docsgpt-curl https://127.0.0.1/api/sources | jq -r '.[] | .name' | sort
ingest: SUCCESS
harbour-lane-servicing
Step 8: Ask questions
- Select New Chat.
- Select Knowledge under the message box and choose the sources to search.
- Type your question and press Enter. The answer appears with Sources: select a source card to see the passage it came from.

The same through the API:
SRC=$(curl -sk -K ~/.docsgpt-curl https://127.0.0.1/api/sources | jq -r '.[] | select(.name=="harbour-lane-servicing") | .id')
curl -sk -K ~/.docsgpt-curl -H 'Content-Type: application/json' \
-d "{\"question\":\"How much does a full overhaul cost and how long does it take?\",\"active_docs\":\"$SRC\",\"history\":\"[]\"}" \
https://127.0.0.1/api/answer | jq -r '.answer, (.sources[] | "source: \(.title)")'
Example output (the answer is generated, so your wording will differ):
A full overhaul costs 140 GBP and takes five working days.
source: harbour-lane-servicing.md
/stream returns the same answer as server-sent events while it is generated. The full API reference is at docs.docsgpt.cloud; every call to this VM needs the password as shown above.
Speed tips for the local model. DocsGPT retrieves six passages for each question by default, and most of the answer time on a CPU is the model reading them. To retrieve fewer, open Settings > Knowledge, select the menu on a source, choose Source settings and lower Chunks to retrieve (top-k) (it takes effect immediately, no re-indexing); through the API, add "chunks": 3 to the request. Fewer passages mean a shorter prompt and a faster answer, at the cost of context. Short, focused documents also help. For production use, connect a cloud model (Step 10).
Step 9: Understand the access model
- Sign in. nginx asks for this VM's password on every page and every API call: the web UI, uploads, website imports,
/api/answer,/stream, agent and widget endpoints, webhooks, everything. The password travels only over HTTPS (with HSTS), nginx removes it before the request reaches DocsGPT, and DocsGPT sets no cookies. Wrong passwords are refused with401. - Cross-site requests are refused. Browsers re-send a site's password automatically, so another website you visit could otherwise make your browser act on DocsGPT. nginx refuses, with
403, any change (POST, PUT, PATCH, DELETE) whoseOriginorRefereris another site, and any request another site's page makes in the background (images, scripts, fetches) even if it carries the password. Following a link to DocsGPT from elsewhere still opens it, and API clients such ascurlor scripts, which send noOrigin, work normally. DocsGPT's permissive CORS headers are removed, so no other website can read its responses. - One workspace. Everyone with the password shares the same DocsGPT workspace, documents and conversations. If you need separate user accounts, DocsGPT supports single sign on through OpenID Connect (
AUTH_TYPE=oidcwith your own identity provider; see the DocsGPT documentation). - Agents and widgets. DocsGPT agents have API keys for embedding a chat widget in another website. On this VM those endpoints are behind the same password and the cross-site rule, so a widget on another site will not work until you deliberately open those paths in nginx.
- Network. nginx is the only public listener: it serves DocsGPT on port
443with a certificate generated for this VM, and port80only redirects to HTTPS. DocsGPT listens on127.0.0.1:7091. PostgreSQL and Valkey are on a private Docker network and require their per-VM passwords. - The local model. Ollama has no login of its own, so it listens only on the VM's loopback address. The DocsGPT containers reach it through the model gateway on
172.30.252.1:11435, which needs a per-VM key and passes only the OpenAI style/v1/API (so nothing on the network can pull or delete models). A firewall rule lets only the DocsGPT backend and worker containers reach the gateway. - Fail closed. DocsGPT, Ollama and the gateway start only after first boot has written this VM's secrets, and nginx only after first boot has proven the password gate. If first boot fails, it removes its markers and stops everything, so nothing serves a half-configured VM. Before every start, DocsGPT's unit also refuses to run if a secret is missing or an upstream default, or if a third-party setting was turned on without an explicit opt-in.

In this check, 405 means the request reached DocsGPT with the correct password but that route only accepts POST. You can check the gate yourself:
code() { curl -sk -o /dev/null -w '%{http_code}' "$@"; }
echo "anonymous UI : $(code https://127.0.0.1/)"
echo "anonymous answer API : $(code -X POST https://127.0.0.1/api/answer)"
echo "anonymous upload : $(code -X POST https://127.0.0.1/api/upload)"
echo "with this VM's password: $(code -K ~/.docsgpt-curl https://127.0.0.1/api/config)"
echo "plain HTTP : $(code http://127.0.0.1/)"
echo "cross-site POST : $(code -K ~/.docsgpt-curl -X POST -H 'Origin: https://other-site.example' https://127.0.0.1/api/answer)"
Expected output:
anonymous UI : 401
anonymous answer API : 401
anonymous upload : 401
with this VM's password: 200
plain HTTP : 301
cross-site POST : 403
Outbound requests (SSRF protection). DocsGPT fetches web pages when you import a website, and calls the model providers you configure. A firewall rule applied before any container starts stops the DocsGPT containers from reaching the Azure Instance Metadata Service (169.254.169.254), the Azure wire server (168.63.129.16), loopback, your private address ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 100.64.0.0/10), link-local and other reserved ranges, and every service on the VM except the model gateway. Between the DocsGPT containers only the connections the application needs are allowed (the API and worker to PostgreSQL and Valkey, the worker to the API), so a fetched URL cannot reach another container either. Because the check is on the network packets, it also holds when a URL redirects or when a host name resolves to one of those addresses. DocsGPT also validates URLs itself; the firewall is the second, independent layer. Check it from inside the worker, the container that fetches URLs:
sudo docker exec -i docsgpt-worker-1 python - <<'EOF'
import socket
def reach(host, port):
try:
socket.create_connection((host, port), timeout=5).close()
return "open"
except OSError:
return "blocked"
for name, host, port in [("Azure IMDS ", "169.254.169.254", 80),
("Azure WireServer", "168.63.129.16", 80),
("private network ", "10.0.0.1", 80),
("model gateway ", "172.30.252.1", 11435),
("internet ", "www.example.com", 443)]:
print(name, reach(host, port))
EOF
Expected output:
Azure IMDS blocked
Azure WireServer blocked
private network blocked
model gateway open
internet open

Reaching a private address on purpose. If you want DocsGPT to import from a server on your own network, or to use a model behind a private endpoint, add that address to /etc/docsgpt/egress-allow (one entry per line, optionally limited to a TCP port) and restart Docker. The metadata service, the wire server and loopback can never be allowed:
echo "10.20.30.40 tcp 443" | sudo tee -a /etc/docsgpt/egress-allow
sudo systemctl restart docker docsgpt
DocsGPT's own URL check also refuses private addresses for website imports, so this is mainly for model and connector endpoints.
Step 10: What leaves the VM, and connecting a cloud model
By default nothing does. These settings in /etc/docsgpt/docsgpt.env (readable by root only) keep it that way:
sudo grep -E '^(LLM_PROVIDER|LLM_NAME|OPENAI_BASE_URL|VERSION_CHECK|TTS_PROVIDER|STT_PROVIDER|ORT_DISABLE_TELEMETRY|HF_HUB_OFFLINE|BACKGROUND_JOBS_ENABLED|MONITORS_ENABLED)=' /etc/docsgpt/docsgpt.env
LLM_PROVIDER=openai
LLM_NAME=qwen2.5:1.5b
OPENAI_BASE_URL=http://172.30.252.1:11435/v1
VERSION_CHECK=false
TTS_PROVIDER=none
STT_PROVIDER=none
ORT_DISABLE_TELEMETRY=1
HF_HUB_OFFLINE=1
BACKGROUND_JOBS_ENABLED=false
MONITORS_ENABLED=false
OPENAI_BASE_URLpoints DocsGPT at the bundled model through the model gateway. While it is set, DocsGPT also hides its hosted Arc53 model and the cloud OpenAI catalogueVERSION_CHECK=falsestops DocsGPT reporting its version with an instance identifier to Arc53 every few hoursTTS_PROVIDERandSTT_PROVIDERare off: upstream sends text to Google for speech and audio to OpenAI for transcriptionORT_DISABLE_TELEMETRYstops the ONNX runtime that runs the embedding model from sending usage telemetry to Microsoft, andHF_HUB_OFFLINEkeeps the embedding model from contacting Hugging Face (it is already on the VM)BACKGROUND_JOBS_ENABLEDandMONITORS_ENABLEDare off because their tool descriptions add about 2,500 tokens of tool definitions to every question, which more than doubled answer times on the local model (67 seconds instead of 24 in our test). Turn them back on when you use a cloud model

Add a cloud model from the web interface. Select Settings > Custom Models > Add model and enter an OpenAI compatible endpoint: its Base URL, Model ID and API key (Test connection checks them). It then appears in the model menu next to qwen2.5:1.5b, and you can choose per chat. Questions you ask with that model, and the passages DocsGPT retrieves for them, are sent to that provider.
Or make a cloud model the default. Edit /etc/docsgpt/docsgpt.env as root and restart DocsGPT. For example, Azure OpenAI through its OpenAI compatible endpoint (use your resource name, key and the name of your chat deployment):
LLM_PROVIDER=openai
LLM_NAME=YOUR_DEPLOYMENT_NAME
OPENAI_BASE_URL=https://YOUR_RESOURCE.openai.azure.com/openai/v1
OPENAI_API_KEY=YOUR_AZURE_OPENAI_KEY
API_KEY=YOUR_AZURE_OPENAI_KEY
Or Anthropic: set LLM_PROVIDER=anthropic and ANTHROPIC_API_KEY=sk-YOUR..., set LLM_NAME to a model id from the DocsGPT documentation, and remove OPENAI_BASE_URL, OPENAI_API_KEY and API_KEY. Then:
sudo systemctl restart docsgpt
The documents themselves are still indexed on the VM by the local embedding model; only questions and the retrieved passages go to the provider you chose.
Opting in to Arc53's hosted model. Upstream DocsGPT's default is a free hosted model run by Arc53, which receives your questions and the retrieved passages from your documents. If you want it, choose it deliberately: in /etc/docsgpt/docsgpt.env set LLM_PROVIDER=docsgpt, remove the LLM_NAME, OPENAI_BASE_URL, OPENAI_API_KEY and API_KEY lines, add CLOUDIMG_OPT_IN_ARC53_MODEL=yes, and restart DocsGPT. Without that opt-in line DocsGPT refuses to start rather than send your content to a third party by accident. The version check works the same way (VERSION_CHECK=true plus CLOUDIMG_OPT_IN_VERSION_CHECK=yes).
Step 11: Keep the local model and add others
The bundled model stays loaded in memory so the first question never waits for it:
curl -s http://127.0.0.1:11434/api/ps | jq -r '.models[] | "\(.name) \(.details.parameter_size) \(.details.quantization_level)"'
qwen2.5:1.5b 1.5B Q4_K_M
To try a larger local model, choose one whose licence suits you, pull it into Ollama, add its name to LLM_NAME (comma separated, for example LLM_NAME=qwen2.5:1.5b,qwen2.5:7b) and restart DocsGPT:
sudo -u ollama env HOME=/var/lib/ollama OLLAMA_HOST=127.0.0.1:11434 /opt/ollama/bin/ollama pull qwen2.5:7b
sudo systemctl restart docsgpt
Larger models answer better but much more slowly on a CPU and need more memory: allow roughly the model's download size again in free RAM.
Step 12: Use your own domain and a trusted certificate
Point a DNS record at the VM's public IP, open port 80 to the internet for the certificate check, then replace the self-signed certificate with one from Let's Encrypt:
sudo apt-get install -y certbot
sudo certbot certonly --webroot -w /var/www/html -d docs.example.com
sudo sed -i \
-e 's#/etc/docsgpt/tls/server.crt#/etc/letsencrypt/live/docs.example.com/fullchain.pem#' \
-e 's#/etc/docsgpt/tls/server.key#/etc/letsencrypt/live/docs.example.com/privkey.pem#' \
/etc/nginx/sites-available/docsgpt
sudo nginx -t && sudo systemctl reload nginx
Certbot renews the certificate automatically; add --deploy-hook "systemctl reload nginx" to the certonly command so nginx picks up each renewal.
Step 13: Day-2 operations
Logs and status.
sudo tail -n 4 /var/log/docsgpt-firstboot.log | cut -c28-
sudo docker compose -f /etc/docsgpt/compose.yaml logs --tail 3 backend
The first boot log never contains a password or key.
Restart. sudo systemctl restart docsgpt restarts the DocsGPT containers (about 30 seconds until the UI answers again). sudo systemctl restart ollama restarts the local model server and loads the model again.
Back up. Everything DocsGPT stores (database, uploaded files, indexes) is under /var/lib/docsgpt, and its settings and secrets are in /etc/docsgpt. Stop DocsGPT for a consistent copy:
sudo systemctl stop docsgpt
sudo tar -C / -czf /root/docsgpt-backup-$(date +%F).tar.gz var/lib/docsgpt etc/docsgpt
sudo systemctl start docsgpt
Copy the archive off the VM. It contains your secrets and documents, so keep it as private as the VM itself. You can also snapshot the VM's OS disk in Azure.
Updates. Ubuntu security updates install automatically. DocsGPT, PostgreSQL and Valkey are pinned to image digests in /etc/docsgpt/compose.yaml for a repeatable deployment. To move to a later DocsGPT release, back up first, replace the arc53/docsgpt@sha256:... reference with the new release's digest from Docker Hub, run sudo docker compose -f /etc/docsgpt/compose.yaml pull and restart DocsGPT; it migrates its database on start.
Troubleshooting.
- The browser shows 502 Bad Gateway. DocsGPT is still starting (after a reboot or restart it takes about 30 seconds). Wait and reload.
- The browser keeps asking for the password. Use the user name
adminand the password from/root/docsgpt-credentials.txt, or set a new one withhtpasswd(Step 6). - Answers are slow. The local model runs on the CPU. Lower the number of chunks (Step 8), use a non-burstable VM size, or connect a cloud model (Step 10). On a B-series VM, check the CPU credits in the Azure Portal under the VM's Metrics.
- A website import fails. The firewall blocks private addresses (Step 9); public websites work. Check
sudo docker compose -f /etc/docsgpt/compose.yaml logs --tail 50 worker. - DocsGPT does not start after you edited
docsgpt.env. Runsudo /usr/local/sbin/docsgpt-preflight: it prints the setting it refuses and why. - First boot did not finish. Read
/var/log/docsgpt-firstboot.log.
Support
cloudimg provides 24/7 support for this image. Contact support@cloudimg.co.uk with your VM's region and the output of sudo tail -n 50 /var/log/docsgpt-firstboot.log.