Milvus 2.6.25 on AWS User Guide
Overview
This guide covers launching and using the Milvus 2.6.25 on Ubuntu 24.04 AMI from cloudimg on Amazon EC2. It is one version of the cloudimg vector databases and RAG listing on AWS Marketplace; you pick it as the software version when you subscribe and launch.
Milvus is an open source vector database, a graduated project of the LF AI & Data Foundation. It stores embedding vectors next to scalar fields and answers nearest neighbour searches over millions to billions of vectors in milliseconds, with HNSW, IVF, DiskANN, sparse (BM25 full text) and other index types. It is the retrieval layer of many retrieval augmented generation (RAG), semantic search, recommendation and image search systems. Applications talk to it with the official SDKs (Python pymilvus, Java, Go, Node.js), which use gRPC, or with its REST API.
This image runs Milvus standalone: the coordinator, proxy, query, data and streaming nodes in one process, with its metadata store (an embedded etcd), its object storage (local files) and its write-ahead log (Woodpecker on local files) all inside that process and on the instance's data volume. There is no Docker, no MinIO and no separate etcd to look after.
The cloudimg image ships it the secure way:
- Authentication on, with a root password unique to your instance. Milvus normally starts with authentication off, and when it is turned on the
rootuser's password isMilvus. On this image authentication is on, the data volume ships empty, and first boot generates a 40 character password on the instance and hands it to Milvus as it creates therootuser, so the default password is never valid, not even for a moment. The password is written to/root/milvus-credentials.txt(root only). - HTTPS from the first boot, for gRPC and REST. nginx serves both the Milvus gRPC API (what every SDK uses) and the REST API on port 443, over TLS with a certificate generated on your instance's first boot (HTTP/2). Port 80 redirects to HTTPS. Credentials only ever cross the network inside TLS.
- Every Milvus port on localhost only. Upstream Milvus binds its proxy, internal component ports, management port and (in standalone) its etcd on every network interface. cloudimg's build binds every one of them to
127.0.0.1; a kernel filter on the Milvus service lets its sockets talk to loopback addresses only; a firewall table drops those ports on the network interfaces; and on the instance itself only the Milvus service account can open the internal ports. nginx is the only network listener. - Rebuilt from source, patched. The official Milvus 2.6.25 binary was built with an older Go toolchain and Go libraries that have published security fixes. cloudimg rebuilds the Milvus binary from the
v2.6.25source with Go 1.26.10 and patched Go modules (gRPC, etcd, OpenTelemetry, x/net and others), links it with the same release's C++ search engine, and uses Ubuntu's own (security updated) OpenSSL instead of the older copy upstream bundles. It also carries two cloudimg source patches, shipped on the image as/usr/share/doc/cloudimg/milvus/cloudimg-source.patch: every Milvus socket binds to localhost, and a fix for an upstream bug that aborted Milvus with a core dump on every graceful stop. These are cloudimg changes to the v2.6.25 source, not an upstream release; the stop fix is dropped once upstream ships its own. - Closed until first boot, and fail closed. Milvus cannot initialise its data volume without first boot's password, and nginx ships switched off. First boot opens the public listener only after Milvus works on loopback, the default and anonymous logins are refused and an authenticated check passes; if anything fails, the listener is closed again. The service also refuses to start if its configuration ever turns authentication off, moves a port off localhost, switches to remote storage, enables the v1 REST API, profiling, tracing or the management API, or finds its data volume missing.
- Your data on its own disk.
/var/lib/milvus(metadata store, segments and indexes, write-ahead log) is a separate 40 GiB EBS volume that you can resize independently of the operating system. - Hardened defaults. Milvus runs as its own unprivileged account in a systemd sandbox that can write only to its data volume, with core dumps off. It can make no outbound connection and cannot reach the instance metadata service (see Step 11 for embedding functions). nginx is blocked from the instance metadata service too. The AMI requires IMDSv2. Requests for any host name the instance does not serve are dropped.
- Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.
What is on the image: Milvus 2.6.25 (/opt/milvus/bin/milvus, built from source by cloudimg when the image was made, and its C++ engine libraries in /opt/milvus/lib), nginx, Ubuntu 24.04 LTS, cloud-init and the AWS Systems Manager agent. The data volume ships empty: no collection, no user.
Default user: ubuntu · Architecture: x86_64 · Recommended instance type: m5.large
Prerequisites
- An AWS account subscribed to the listing, an EC2 key pair and a VPC subnet with a route to the internet (or a private route you use for management).
- A security group that allows TCP 22 (SSH), TCP 443 (the Milvus gRPC and REST APIs) and TCP 80 (redirects to HTTPS) from your own networks only. Never open 19530, 9091, 2379 or the other Milvus ports: on this image they are internal to the instance.
- For the SDK examples, a machine with Python 3.9+ and
pip install "pymilvus==2.6.*"(or another Milvus SDK).
Step 1: Launch the instance
In the AWS Marketplace listing choose Continue to Subscribe, then Continue to Configuration, pick Milvus 2.6.25 on Ubuntu 24.04 as the software version and your Region, then Launch through EC2. Choose m5.large or larger (Milvus keeps loaded collections and their indexes in memory, so size the instance's memory for your data), your key pair and a security group as above. The AMI brings two EBS volumes: the root volume and a 40 GiB data volume for /var/lib/milvus; enlarge the data volume at launch if you expect a large dataset.
With the AWS CLI (replace the values in angle brackets):
aws ec2 run-instances --region <region> --image-id <ami-id-from-the-listing> \
--instance-type m5.large --key-name <your-key-pair> \
--security-group-ids <your-security-group> --subnet-id <your-subnet> \
--metadata-options HttpTokens=required,HttpEndpoint=enabled \
--block-device-mappings 'DeviceName=/dev/sdf,Ebs={VolumeSize=100,VolumeType=gp3}' \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=milvus}]'
Step 2: Connect to your instance
| Version | SSH user |
|---|---|
| Milvus 2.6.25 on Ubuntu 24.04 | ubuntu |
ssh -i <your-key.pem> ubuntu@<public-ip>
Step 3: Check the services
First boot generates the certificate and the root password, initialises Milvus with that password, restarts it, opens nginx and runs an authenticated check before it finishes (about two minutes):
systemctl is-active milvus nginx milvus-firstboot milvus-port-guard
sudo test -f /var/lib/cloudimg/milvus-firstboot.done && echo FIRSTBOOT_DONE
active
active
active
active
FIRSTBOOT_DONE
Every Milvus socket belongs to the milvus process on 127.0.0.1; nginx (80, 443) and SSH (22) are the only services reachable from the network:
sudo ss -lntpH | grep -v '127.0.0.5' | awk '{split($6, p, "\""); print $4, p[2]}' | sort -u
0.0.0.0:22 sshd
0.0.0.0:443 nginx
0.0.0.0:80 nginx
127.0.0.1:19529 milvus
127.0.0.1:19530 milvus
127.0.0.1:21123 milvus
127.0.0.1:21124 milvus
127.0.0.1:22125 milvus
127.0.0.1:22222 milvus
127.0.0.1:2379 milvus
127.0.0.1:2380 milvus
127.0.0.1:9091 milvus
[::]:22 sshd
[::]:443 nginx
[::]:80 nginx
19530 is the Milvus proxy (gRPC and REST), 19529, 21123, 21124, 22125 and 22222 are its internal components, 9091 is its health and metrics port and 2379/2380 its embedded etcd. From another machine none of them answers.
Step 4: Get your connection details
sudo grep -E '^MILVUS_' /root/milvus-credentials.txt
The file is readable by root only:
MILVUS_URI=https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com
MILVUS_USER=root
MILVUS_PASSWORD=<MILVUS_PASSWORD>
MILVUS_URIis the endpoint for every SDK and for the REST API. It uses the instance's public DNS name from EC2 instance metadata (the public IP address when the subnet has no public DNS names); the certificate also names the public and private IP addresses. To serve Milvus under your own DNS name, see Step 10.MILVUS_USERandMILVUS_PASSWORDare the Milvusrootuser, which can do everything, including creating users and roles (Step 8). SDKs take them as the tokenroot:<MILVUS_PASSWORD>; the REST API takes the same token asAuthorization: Bearer root:<MILVUS_PASSWORD>.
The certificate is self signed. Copy /etc/ssl/milvus/milvus.crt to your client machine and pass it to the SDK (server_pem_path), or install your own certificate (Step 10).
Step 5: Confirm the API requires the password
Milvus refuses a REST call without valid credentials with "code":1800 and a gRPC call with status 16 (UNAUTHENTICATED). The examples read the password from the credentials file and hand it to curl as a configuration file on standard input (-K -), so it never appears on a command line or in your shell history:
C=/etc/ssl/milvus/milvus.crt; U=https://127.0.0.1/v2/vectordb/collections/list
curl -s --cacert $C -X POST -H 'Content-Type: application/json' -d '{}' $U; echo
printf 'header = "Authorization: Bearer root:Milvus"\n' | curl -s --cacert $C -K - -X POST -H 'Content-Type: application/json' -d '{}' $U; echo
printf 'header = "Authorization: Bearer root:wrong-password"\n' | curl -s --cacert $C -K - -X POST -H 'Content-Type: application/json' -d '{}' $U; echo
sudo sed -n 's/^MILVUS_PASSWORD=\(.*\)/header = "Authorization: Bearer root:\1"/p' /root/milvus-credentials.txt | curl -s --cacert $C -K - -X POST -H 'Content-Type: application/json' -d '{}' $U; echo
curl -s --cacert $C https://127.0.0.1/healthz; echo
{"code":1800,"message":"user hasn't authenticated"}
{"code":1800,"message":"user hasn't authenticated"}
{"code":1800,"message":"user hasn't authenticated"}
{"code":0,"data":[]}
OK
/healthz stays open for load balancers: it reports whether Milvus is healthy and reveals nothing. From another machine, use MILVUS_URI instead of https://127.0.0.1.
Step 6: Create a collection, insert vectors and search (Python SDK)
On your client machine (with pymilvus installed and the instance's certificate copied to milvus.crt), connect with the URI and token from Step 4. The SDK speaks gRPC over HTTPS through port 443:
from pymilvus import MilvusClient
client = MilvusClient(
uri="https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com",
token="root:<MILVUS_PASSWORD>",
server_pem_path="milvus.crt",
)
client.create_collection("films", dimension=4, metric_type="L2")
client.insert("films", [
{"id": 1, "vector": [0.9, 0.1, 0.1, 0.0], "title": "Carol"},
{"id": 2, "vector": [0.1, 0.2, 0.3, 0.4], "title": "Wonder Woman"},
{"id": 3, "vector": [0.1, 0.8, 0.2, 0.1], "title": "Life of Pi"},
{"id": 4, "vector": [0.2, 0.3, 0.3, 0.4], "title": "Mad Max: Fury Road"},
])
hits = client.search("films", data=[[0.1, 0.2, 0.3, 0.35]], limit=2, output_fields=["title"])
print([(h["entity"]["title"], round(h["distance"], 4)) for h in hits[0]])
[('Wonder Woman', 0.0025), ('Mad Max: Fury Road', 0.0225)]
The quick setup above creates an id primary key, a 4 dimension vector field with an index, and a dynamic field for everything else (title); distance is the L2 distance (smaller is closer). In a real application you store the embeddings your own model produces (any dimension) and choose the schema, metric and index explicitly; the Milvus documentation describes each index type and its parameters, and searches can also filter on scalar fields. A wrong token, the default root:Milvus or no token is refused: the client raises a MilvusException instead of connecting.
Step 7: The same with the REST API, and the built in check
Every operation is also available as JSON over HTTPS under /v2/vectordb/. On the instance:
C=/etc/ssl/milvus/milvus.crt; U=https://127.0.0.1/v2/vectordb
m() { sudo sed -n 's/^MILVUS_PASSWORD=\(.*\)/header = "Authorization: Bearer root:\1"/p' /root/milvus-credentials.txt | curl -s --cacert "$C" -K - -X POST -H 'Content-Type: application/json' "$@"; echo; }
m -d '{"collectionName":"movies","dimension":4,"metricType":"L2"}' $U/collections/create
m -d '{"collectionName":"movies","data":[{"id":1,"vector":[0.9,0.1,0.1,0.0],"title":"Carol"},{"id":2,"vector":[0.1,0.2,0.3,0.4],"title":"Wonder Woman"}]}' $U/entities/insert
sleep 2
m -d '{"collectionName":"movies","data":[[0.1,0.2,0.3,0.35]],"limit":1,"outputFields":["title"]}' $U/entities/search
m -d '{"collectionName":"movies"}' $U/collections/drop
{"code":0,"data":{}}
{"code":0,"cost":0,"data":{"insertCount":2,"insertIds":[1,2]}}
{"code":0,"cost":0,"data":[{"distance":0.002500001,"id":2,"title":"Wonder Woman"}],"topks":[1]}
{"code":0,"data":{}}
The image also ships an end to end check you can run at any time; first boot runs a read only version of it. It reads the credentials file itself and talks to Milvus over HTTPS through nginx with the instance's certificate pinned: port 80 redirects, an unknown host name is dropped, no password, a wrong password and the default root:Milvus are refused over both REST and gRPC while the root password works, and root creates a temporary collection whose nearest neighbour search returns the right vector, before the collection is dropped:
sudo milvus-verify.sh
port 80 -> 301 https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com/ ; an unknown Host is dropped on 80 and 443 ; certificate verifies for ec2-<public-ip-dashed>.<region>.compute.amazonaws.com ; /healthz OK
auth: REST code 1800 and gRPC status 16 with no / a wrong / the default root:Milvus credential; code 0 / status 0 with root
round trip: root created cloudimg_verify_<n> (4-dim, L2), inserted 2 vectors, the nearest neighbour of [0.11,0.2,0.3,0.4] is id 1; a wrong password cannot insert (1800); collection dropped
MILVUS_ROUNDTRIP_OK
Step 8: Users and roles
Milvus has role based access control. Create a user for each application rather than sharing root, and grant it a role with only the privileges it needs. For example, a read only user for one collection (run on your client machine with the root token):
client.create_user(user_name="app_reader", password="<a-long-random-password>")
client.create_role(role_name="reader")
client.grant_privilege(role_name="reader", object_type="Collection", privilege="Search", object_name="films")
client.grant_privilege(role_name="reader", object_type="Collection", privilege="Query", object_name="films")
client.grant_role(user_name="app_reader", role_name="reader")
app_reader can now search and query films but cannot insert, delete or create collections. See the Milvus RBAC documentation for privilege groups and database level roles.
Step 9: Security checks
The files that matter are locked down:
sudo stat -c '%a %U:%G %n' /root/milvus-credentials.txt /var/lib/milvus /etc/ssl/milvus/milvus.key /etc/milvus/user.yaml
600 root:root /root/milvus-credentials.txt
750 milvus:milvus /var/lib/milvus
600 root:root /etc/ssl/milvus/milvus.key
644 root:root /etc/milvus/user.yaml
How the binary was built is recorded on the image, with the govulncheck result and cloudimg's two source patches:
sha256sum /opt/milvus/bin/milvus
grep -E '^(source|toolchain|binary|govulncheck) ' /usr/share/doc/cloudimg/milvus/BUILD-PROVENANCE.txt
6b201a56a290bd1cd834b8d97fbcce310a0c884c3231e903b64cb62f88fd06af /opt/milvus/bin/milvus
source https://github.com/milvus-io/milvus tag v2.6.25 (commit 95ec6785266f284d4bfe9c0d7a56f5390243a6b1), archive https://github.com/milvus-io/milvus/archive/refs/tags/v2.6.25.tar.gz
source patches cloudimg-source.patch: (1) every Milvus server socket binds MILVUS_LISTEN_HOST (127.0.0.1 on this image)
toolchain go1.26.10 linux/amd64, official tarball https://go.dev/dl/go1.26.10.linux-amd64.tar.gz (sha256 ccfe7ae822d2c2f41f4fe7c956199967a4dac22d0ee0d2b2bfdb440aab3b20c5); cgo with gcc (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0
binary /opt/milvus/bin/milvus sha256 6b201a56a290bd1cd834b8d97fbcce310a0c884c3231e903b64cb62f88fd06af
govulncheck v1.9.0 -mode=binary: only GO-2026-5046 GO-2026-5047 GO-2026-5048 called (github.com/hamba/avro/v2 v2.29.0: Avro decoder
Milvus runs unprivileged in a sandbox that can write only to its data volume, may exchange packets with loopback addresses only and never writes a core dump; nginx cannot reach the instance metadata service either:
systemctl show milvus -p User -p ProtectSystem -p ReadWritePaths -p NoNewPrivileges -p LimitCORE -p IPAddressDeny -p IPAddressAllow
systemctl show nginx -p IPAddressDeny
IPAddressAllow=::1/128 127.0.0.0/8
IPAddressDeny=::/0 0.0.0.0/0
LimitCORE=0
User=milvus
ReadWritePaths=/var/lib/milvus
ProtectSystem=strict
NoNewPrivileges=yes
IPAddressDeny=168.63.129.16/32 fd00:ec2::254/128 169.254.169.254/32
Only the Milvus service account can open its internal ports (the embedded etcd holds the user records), and the API and health ports only accept the Milvus account, nginx and root:
for p in 2379 22125 19529 19530 9091; do curl -s -m 5 -o /dev/null -w "port $p as $(id -un) -> %{http_code}\n" http://127.0.0.1:$p/ || true; done
sudo nft list chain inet cloudimg_milvus input | grep drop
port 2379 as ubuntu -> 000
port 22125 as ubuntu -> 000
port 19529 as ubuntu -> 000
port 19530 as ubuntu -> 000
port 9091 as ubuntu -> 000
iifname != "lo" tcp dport { 2379, 2380, 9091, 19529, 19530, 21123, 21124, 22125, 22222 } counter packets 0 bytes 0 drop
nginx passes Milvus a fixed host name and the real client address from the connection, never values a client sends:
grep -hE '(proxy|grpc)_set_header (Host|X-Forwarded-For|X-Real-IP|Forwarded)' /etc/nginx/milvus-proxy.conf /etc/nginx/milvus-grpc.conf
proxy_set_header Host $m_host;
proxy_set_header Forwarded "";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
grpc_set_header Host $m_host;
grpc_set_header Forwarded "";
grpc_set_header X-Real-IP $remote_addr;
grpc_set_header X-Forwarded-For $remote_addr;
The certificate was generated on this instance and names its own addresses:
H=$(sudo sed -n 's#^MILVUS_URI=https://\(.*\)#\1#p' /root/milvus-credentials.txt)
echo | openssl s_client -connect 127.0.0.1:443 -servername "$H" 2>/dev/null | openssl x509 -noout -subject -ext subjectAltName
subject=CN = ec2-<public-ip-dashed>.<region>.compute.amazonaws.com, O = cloudimg
X509v3 Subject Alternative Name:
DNS:ec2-<public-ip-dashed>.<region>.compute.amazonaws.com, IP Address:<public-ip>, IP Address:<private-ip>, DNS:ip-<private-ip-dashed>.ec2.internal, IP Address:127.0.0.1, DNS:localhost
The password reached no log, the journal, shell history, backups, /etc, the data volume (Milvus stores only a hash of it) or the Milvus process environment:
sudo milvus-secret-leak-check.sh
LEAKCHECK_OK the root password is in no journal, auth.log, syslog, cloud-init, nginx log, shell history, MOTD, /var/backups, /etc, /usr/local, /opt, /tmp, the data volume or the Milvus process environment
Step 10: Your own DNS name and certificate, and a new root password
Point a DNS record at the instance, then set the name Milvus is served as. This mints a new self signed certificate for the name, updates nginx's host rule and the URI in /root/milvus-credentials.txt, reloads nginx and keeps the name across reboots:
sudo milvus-set-hostname <your-domain>
Without a configured name, the instance re-reads its address from EC2 instance metadata at every boot, so a stop and start that changes the public IP address keeps the API reachable. To use a certificate from your own certificate authority instead, copy it over /etc/ssl/milvus/milvus.crt and milvus.key (key mode 0600) and run sudo systemctl reload nginx; running milvus-set-hostname again replaces it with a self signed one.
To generate a new root password (if it was ever exposed), run:
sudo milvus-rotate-root-password
It changes root's password through the API (proving the old one), checks that the old password is refused and the new one works, and rewrites /root/milvus-credentials.txt. Update every client that used the old password.
Step 11: Outbound connections and embedding functions (off by default)
Milvus needs no outbound connection to store and search vectors. Its optional functions (text embedding and reranking) call model providers such as OpenAI, Bedrock, Cohere, Hugging Face, or a TEI or vLLM endpoint named in a collection schema, from the server. This image blocks every outbound connection from the Milvus service, so such a call cannot be pointed at the instance metadata service or anything else on your network.
To use functions, allow outbound access by removing the drop-in and restarting Milvus, configure the provider credentials in /etc/milvus/user.yaml (see the Milvus documentation), and only name endpoints you trust:
sudo rm /etc/systemd/system/milvus.service.d/60-cloudimg-egress.conf
sudo systemctl daemon-reload && sudo systemctl restart milvus
Removing it also lets packets from other machines reach Milvus's sockets again; they are still bound to 127.0.0.1 and the cloudimg_milvus firewall table still drops every Milvus port on the network interfaces. Milvus stays blocked from the instance metadata service (the other drop-in, 50-cloudimg-imds-deny.conf), so give providers an API key rather than relying on an instance role. To close outbound access again, recreate the file with IPAddressAllow=localhost and IPAddressDeny=any under [Service].
Step 12: Data volume, snapshots and backups
The data directory is its own EBS volume, mounted by filesystem UUID:
findmnt -n -o SOURCE,FSTYPE,TARGET /var/lib/milvus; df -h /var/lib/milvus | tail -1
/dev/nvme1n1 ext4 /var/lib/milvus
/dev/nvme1n1 40G 123M 37G 1% /var/lib/milvus
To grow it, enlarge the volume in the EC2 console (or with aws ec2 modify-volume), then run sudo resize2fs /dev/nvme1n1 on the instance; no restart is needed. If the volume is ever missing, Milvus refuses to start rather than write your data to the root disk.
EBS snapshots of the data volume are the simplest whole dataset backup: for a consistent copy, stop Milvus (sudo systemctl stop milvus; a clean stop takes a minute or two while it flushes every channel), snapshot the volume, and start it again. The data volume holds the user records (password hashes), so treat its snapshots as secret.
Step 13: Configuration
Upstream's defaults for this release are in /etc/milvus/milvus.yaml (leave it unchanged); cloudimg's settings and yours go in /etc/milvus/user.yaml, which overrides it. Edit it (for example query node memory or quota settings; see the Milvus configuration reference) and restart:
sudo nano /etc/milvus/user.yaml
sudo systemctl restart milvus
Keep authorizationEnabled: true, every component ip: 127.0.0.1, the embedded etcd, storageType: local, mq.type: woodpecker with woodpecker.storage.type: local, enableV1: false, enablePprof: false, managementMetricsOnly: true and trace.exporter: noop: the service refuses to start otherwise (journalctl -u milvus shows the reason). Do not set settings through environment variables either. This image runs Milvus standalone on local storage; it is not set up to join a cluster or to use S3 or MinIO object storage.
Step 14: Server components
journalctl -u milvus -o cat --no-pager | grep -m3 -E '^(Version|GitCommit|GoVersion):'
nginx -v 2>&1; lsb_release -ds
ls /usr/share/doc/cloudimg/milvus/
Version: v2.6.25
GitCommit: 95ec6785266f284d4bfe9c0d7a56f5390243a6b1
GoVersion: go version go1.26.10 linux/amd64
nginx version: nginx/1.24.0 (Ubuntu)
Ubuntu 24.04.5 LTS
BUILD-PROVENANCE.txt
LIBRARIES.txt
LICENSE
UPSTREAM-ENGINE-COMPONENTS.txt
cloudimg-source.patch
govulncheck-binary.json
govulncheck-binary.txt
| Component | Version | Notes |
|---|---|---|
| Milvus | 2.6.25 | /opt/milvus/bin/milvus (built from source with Go 1.26.10), service milvus (standalone), data /var/lib/milvus (own EBS volume), logs in the journal |
| Milvus engine | 2.6.25 | upstream's C++ libraries of the same release in /opt/milvus/lib, with Ubuntu's OpenSSL |
| nginx | 1.24.0 | TLS and HTTP/2 on 443 (gRPC and REST), redirect on 80, site /etc/nginx/sites-available/cloudimg-milvus |
| Ubuntu | 24.04 LTS | unattended security upgrades on |
Security notes on bundled components. govulncheck reports three advisories in the Avro decoder used by Milvus's Apache Pulsar client (GO-2026-5046, GO-2026-5047, GO-2026-5048; no fixed version exists): that code only runs when Milvus uses Pulsar as its message queue, and this image uses the embedded Woodpecker log and refuses any other. Upstream's prebuilt C++ engine for the 2.6 line statically contains older client libraries for remote object storage and tracing (libcurl 7.86.0, gRPC C++ 1.50.1, the AWS, Azure and Google Cloud storage SDKs); on this image storage is local, tracing is off and the Milvus service cannot open any network connection off the instance, so that code cannot reach a remote party. The list is in /usr/share/doc/cloudimg/milvus/UPSTREAM-ENGINE-COMPONENTS.txt.
Troubleshooting
SSL certificate problemorcertificate verify failed: the certificate is self signed. Pass--cacert /etc/ssl/milvus/milvus.crtto curl on the instance,server_pem_path="milvus.crt"to pymilvus, or install your own certificate (Step 10).- pymilvus connects to port 19530 and times out: use the
https://URI from the credentials file (it defaults to port 443); the Milvus ports themselves are not reachable from the network on this image. - The connection is closed without a response: the request used a host name the instance does not serve (nginx drops unknown names). Use
MILVUS_URI, the instance's IP address, or set your name withmilvus-set-hostname. milvusdoes not start after a configuration change:journalctl -u milvus -n 20shows whichuser.yamlsetting the safety check refused.