Azure virtual machines
Run polign_db on a plain Azure Linux VM in front of a Blob Storage container in your own subscription. You need the Azure CLI and about ten minutes. You pay Azure for the VM and the storage. The software is free.
What you get
One VM running polign-server as a systemd service, and one Blob Storage
container that holds everything: vectors, indexes, and the write log. The VM is a
serving tier in front of the container. Replacing the VM loses nothing.
The VM reaches the container through its managed identity. No storage account key or connection string is written anywhere, and the VM has no public IP address.
Step 1: Create the storage and the VM
Run these from your own machine after az login. Change the names at the
top. A storage account name has to be globally unique, lowercase, and 3 to 24 letters
or digits.
RG=polign
LOC=westus2
SA=mypolignstore # your storage account name
VM=polign-1
az group create -n $RG -l $LOC
az storage account create -n $SA -g $RG -l $LOC \
--sku Standard_LRS --allow-blob-public-access false
az storage container create --account-name $SA -n polign --auth-mode login
az vm create -g $RG -n $VM \
--image Debian:debian-12:12-gen2:latest --size Standard_D4s_v5 \
--assign-identity --public-ip-address "" \
--admin-username azureuser --generate-ssh-keys
polign_db never creates its own container, so the container has to exist before the
server starts. If az storage container create says you lack permission,
give your own account the Storage Blob Data Contributor role on the storage
account and try again.
For the VM size, serving from the container is bound by network bandwidth and by how much of the working set fits in memory, so prefer memory over vCPUs.
Step 2: Let the VM read and write the container
Give the VM's identity the Storage Blob Data Contributor role on that one
container and nothing else:
PID=$(az vm show -g $RG -n $VM --query identity.principalId -o tsv) SCOPE=$(az storage account show -n $SA -g $RG --query id -o tsv)/blobServices/default/containers/polign az role assignment create --assignee $PID \ --role "Storage Blob Data Contributor" --scope $SCOPE
Role assignments can take a minute or two to take effect. Until then the server restarts every few seconds and logs a permission error. That is expected, and it settles on its own.
Step 3: Install and start the server
Save this as polign-setup.sh. It installs the release binaries, creates
a service account, and starts polign-server under systemd. Change
STORE to match your storage account.
#!/bin/sh
set -eu
STORE=az://mypolignstore/polign/db # az://account/container/prefix
curl -fsSL https://get.polign.com | sh
id polign >/dev/null 2>&1 || useradd --system --create-home \
--home-dir /var/lib/polign --shell /usr/sbin/nologin polign
install -d -o polign -g polign /var/cache/polign
install -d /etc/polign
printf 'POLIGN_STORE=%s\n' "$STORE" > /etc/polign/server.env
cat > /etc/systemd/system/polign-server.service <<'EOF'
[Unit]
Description=polign_db server
After=network-online.target
Wants=network-online.target
[Service]
User=polign
Group=polign
EnvironmentFile=/etc/polign/server.env
Environment=HOME=/var/lib/polign
ExecStart=/usr/local/bin/polign-server -store ${POLIGN_STORE} \
-http 0.0.0.0:23000 -grpc 0.0.0.0:23001 \
-disk-cache-dir /var/cache/polign -disk-cache-bytes 10737418240
Restart=on-failure
RestartSec=2
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now polign-server
The VM has no public IP, so run the script through Azure instead of over SSH:
az vm run-command invoke -g $RG -n $VM \ --command-id RunShellScript --scripts @polign-setup.sh
The disk cache is set to 10 GB. Keep it below the size of the VM's OS disk, or
attach a data disk and point -disk-cache-dir at it.
Step 4: Check that it works
From a machine inside the same virtual network, with IP set to the VM's
private address (az vm list-ip-addresses -g $RG -n $VM shows it):
curl "http://$IP:23000/healthz"
curl -X PUT "http://$IP:23000/v1/collections/docs/vectors/a" \
-d '{"values":[1,0,0],"metadata":{"label":"first"}}'
curl -X POST "http://$IP:23000/v1/collections/docs/query" \
-d '{"values":[0.9,0.1,0],"k":5}'
A collection is created by the first write and takes its size from the first vector. The Python SDK and the HTTP API work against this address the same way they work anywhere else.
Security
- The data plane has no login of its own. Anything that can reach ports 23000 and
23001 can read and write your data, so the network is the boundary. Keep the VM
without a public IP, and never open those ports to
0.0.0.0/0or to theInternetservice tag in the network security group. - The VM's identity can reach one container and nothing else. No storage keys are stored on the VM.
- For shell access without a public IP, use Azure Bastion, or
az ssh vmwith theAADSSHLoginForLinuxextension.
Azure encrypts the storage account at rest, but it does so on its side and sees your
data in the clear on every request. To keep the container from ever holding readable
data, put a keyring file on the VM and name it in
/etc/polign/server.env before the first write:
umask 077 printf '1=%s\n' "$(openssl rand -base64 32)" > /etc/polign/store.keys chown root:polign /etc/polign/store.keys chmod 0640 /etc/polign/store.keys echo 'POLIGN_STORE_ENCRYPTION_KEY_FILE=/etc/polign/store.keys' >> /etc/polign/server.env systemctl restart polign-server
Every object is then encrypted inside the server process, and the disk cache is sealed under the same keys. A store is marked encrypted on its first write and cannot be converted later, so decide this up front. Back up the key file: without it the data cannot be read. The security page covers how this works.
Other ways to sign in to storage
The managed identity above is the recommended path. The server looks for storage credentials in this order, and uses the first one it finds:
AZURE_STORAGE_CONNECTION_STRINGAZURE_STORAGE_KEY, a shared key for the account in the store address- the standard Azure identity chain: service principal variables, workload or
managed identity, then your
az login
If the VM has a user-assigned identity instead of a system-assigned one, add
AZURE_CLIENT_ID=<the identity's client id> to
/etc/polign/server.env. Leave that line out entirely for a system-assigned
identity: if it is present but empty, the server refuses to start.
A storage account in another subscription works the same way as long as it is in the same Entra tenant. Assign the role to the VM's identity on that account.
Operate
- Configuration lives in
/etc/polign/server.envand the unit file. Edit them and runsudo systemctl daemon-reload && sudo systemctl restart polign-server. - Logs:
journalctl -u polign-server. - Index maintenance runs inside the server every 30 minutes. There is nothing to schedule.
Operate in production covers tuning, scaling out, and controlling the bill. On AKS, use the Helm chart with Azure Workload Identity instead of a VM.
Upgrade
Run the install line again and restart:
curl -fsSL https://get.polign.com | sudo sh sudo systemctl restart polign-server
To install a specific release instead of the latest, end the first line with
sudo POLIGN_VERSION=vX.Y.Z sh. The container carries the data, so you can also replace
the VM outright with a fresh one that has the same role. Copy the container first if you
want a way back.
Remove
Delete the VM with az vm delete -g $RG -n $VM. The storage account and
container are not touched, so delete them yourself once you are sure you no longer need
the data. az group delete -n $RG removes everything at once, data
included.
Help
Contact us with the VM name, the region, and the output of
polign-server -version from the VM.