BaseX on Ubuntu 24.04 on Azure User Guide
Overview
BaseX is a lightweight, high performance native XML and JSON database and a fully compliant XQuery 3.1, XPath and XSLT processor. It stores documents in an efficient native store, indexes them for fast full text and structural queries, and answers queries and updates in milliseconds through a clean REST and RESTXQ HTTP API. It ships the DBA web administration application for browsing databases and resources, running interactive XQuery, and managing users, sessions and settings from the browser, and it is a strong foundation for content repositories, configuration stores, data integration and XML processing pipelines.
The cloudimg image installs BaseX at /opt/basex on a headless Java runtime, running as the basexhttp service in local mode bound to loopback 127.0.0.1:8984, behind nginx which terminates TLS. nginx serves the DBA web admin, the REST API and the RESTXQ root on port 443, so credentials never cross the wire in plaintext.
Secure by default, no known credential: a stock BaseX deployment is only as safe as its administrator password. This image never ships a known or default one. The REST API requires HTTP authentication out of the box, and the DBA web admin enforces its own login. A basex-firstboot.service oneshot generates a unique admin password on each VM's first boot, applies it to the database, regenerates a per VM TLS certificate, resolves the instance URL and writes a root only info note, then disables itself. The basexhttp service requires the first boot unit, so it can never serve before that password is set. No two VMs share a password and none is baked into the image.
Dedicated data disk: database content (the BaseX databases, the user store and logs, under DBPATH=/var/lib/basex/data) lives on a dedicated data disk mounted at /var/lib/basex, captured into the image so every VM is provisioned with it. The application jar and web application stay on the OS disk.
What is included:
- BaseX (verified at 12.4) as the official BSD-3-Clause release, on
openjdk-21-jre-headless - The DBA web administration application, served over TLS
basexhttp.servicein local mode bound to loopback127.0.0.1:8984- nginx terminating TLS: DBA, REST and RESTXQ on
443,80redirects to HTTPS basex-firstboot.servicefor the first boot admin password, per VM TLS certificate and info note- A unique per VM admin password generated on first boot, in a root only
0600file - A dedicated data disk mounted at
/var/lib/basexfor databases, the user store and logs - Ubuntu 24.04 LTS base, fully patched
- 24/7 cloudimg support, 24h response SLA
Prerequisites
An active Azure subscription, an SSH key pair, and a VNet with a subnet. BaseX performance and index capacity scale with memory. Recommended VM size: Standard_B2s (2 vCPU, 4 GB RAM) for evaluation and small databases, or a Standard_D4s_v5 or larger for production workloads with large document collections. The dedicated data disk holds your databases, so resize it to suit your dataset.
Step 1: Deploy from the Azure Portal
Search the Marketplace for BaseX on Ubuntu 24.04, choose your VM size, and attach an NSG that allows TCP 22 (SSH) from your management network and TCP 443 (DBA and REST) from the networks and applications that need to reach it. Port 80 only issues an HTTPS redirect.
Step 2: Deploy from the Azure CLI
RG="basex-prod"; LOCATION="eastus"; VM_NAME="basex-01"
GALLERY_IMAGE_ID="/subscriptions/<sub-id>/resourceGroups/azure-cloudimg/providers/Microsoft.Compute/galleries/cloudimgGallery/images/basex-ubuntu-24-04/versions/<version>"
SSH_KEY="$(cat ~/.ssh/id_rsa.pub)"
az group create --name "$RG" --location "$LOCATION"
az network vnet create -g "$RG" --name basex-vnet --address-prefix 10.90.0.0/16 --subnet-name basex-subnet --subnet-prefix 10.90.1.0/24
az network nsg create -g "$RG" --name basex-nsg
az network nsg rule create -g "$RG" --nsg-name basex-nsg --name allow-ssh --priority 100 \
--source-address-prefixes "<your-mgmt-cidr>" --destination-port-ranges 22 --access Allow --protocol Tcp
az network nsg rule create -g "$RG" --nsg-name basex-nsg --name allow-https --priority 110 \
--source-address-prefixes "<your-mgmt-cidr>" --destination-port-ranges 443 --access Allow --protocol Tcp
az vm create -g "$RG" --name "$VM_NAME" --image "$GALLERY_IMAGE_ID" \
--size Standard_B2s --storage-sku StandardSSD_LRS \
--admin-username azureuser --ssh-key-values "$SSH_KEY" \
--vnet-name basex-vnet --subnet basex-subnet --nsg basex-nsg --public-ip-sku Standard
Step 3: Connect via SSH
ssh azureuser@<vm-ip>
Step 4: Verify the services are running
BaseX listens on loopback 127.0.0.1:8984; nginx fronts it with TLS on port 443. The RESTXQ welcome page is public; the REST API and the DBA require authentication.
sudo systemctl is-active basexhttp nginx
ss -tln | grep -E '127.0.0.1:8984|:443 '
curl -ks -o /dev/null -w 'HTTPS root: %{http_code}\n' https://127.0.0.1/
cat /opt/basex/VERSION
You should see both services active, the listening sockets, the root page returning 200, and the installed BaseX version.

The DBA web admin is served over TLS at https://<your-vm-ip>/dba. Because the certificate is self signed per VM, your browser will warn on first visit; accept the exception (or trust /etc/nginx/tls/basex.crt) to reach the sign in page.

Step 5: Read your per VM admin password and confirm auth is enforced
The admin password was generated on this VM's first boot and stored in a root only file. Read it and keep it secret: it authenticates the DBA and every REST request. Confirm that unauthenticated requests, and the stock admin/admin credential, are rejected while the correct password is accepted.
sudo sed -E 's/^(BASEX_ADMIN_PASSWORD=).*/\1********/' /root/basex-info.txt
BASEX_PW=$(sudo grep '^BASEX_ADMIN_PASSWORD=' /root/basex-info.txt | cut -d= -f2-)
echo "no auth -> HTTP $(curl -ks -o /dev/null -w '%{http_code}' https://127.0.0.1/rest)"
echo "stock admin/admin-> HTTP $(curl -ks -o /dev/null -w '%{http_code}' -u admin:admin https://127.0.0.1/rest)"
echo "per-VM admin -> HTTP $(curl -ks -o /dev/null -w '%{http_code}' -u admin:"$BASEX_PW" https://127.0.0.1/rest)"
The info note holds BASEX_ADMIN_PASSWORD and the instance URLs, owned root:root with mode 0600. Unauthenticated and stock admin/admin calls return 401; only the per VM password returns 200.

Sign in to the DBA at https://<your-vm-ip>/dba as admin with the password from the info note. The DBA opens on the Databases panel, listing every database with its resource count, size and last modified time.

Step 6: Create a database and run your first XQuery
Load the admin password into a shell variable, create a library database from an XML document with the REST PUT verb, then run an XQuery that returns the stored titles newest first. BaseX creates the database on PUT and indexes it immediately.
BASEX_PW=$(sudo grep '^BASEX_ADMIN_PASSWORD=' /root/basex-info.txt | cut -d= -f2-)
curl -ks -u admin:"$BASEX_PW" -X PUT -H 'Content-Type: application/xml' --data-binary '<library>
<book id="b1"><title>XQuery and XPath</title><author>Priscilla Walmsley</author><year>2015</year></book>
<book id="b2"><title>Native XML Databases</title><author>Akmal B. Chaudhri</author><year>2003</year></book>
<book id="b3"><title>Designing Data-Intensive Applications</title><author>Martin Kleppmann</author><year>2017</year></book>
</library>' https://127.0.0.1/rest/library
curl -ks -u admin:"$BASEX_PW" --get --data-urlencode \
'query=for $b in db:get("library")//book order by xs:integer($b/year) descending return $b/title/string()' \
https://127.0.0.1/rest/library
The PUT reports that the database was created, and the XQuery returns the three titles ordered by year, newest first.

Step 7: Run XQuery in the DBA editor
The DBA includes an interactive XQuery editor. Open Editor, type a query against your database, and click Run. The results render alongside the query, so you can explore your data without leaving the browser.

Step 8: Browse a database and its indexes
Open a database from the Databases panel to browse its resources, inspect the stored documents, and review its properties and indexes. This is the fastest way to sanity check what BaseX has stored and how it is indexed.
BASEX_PW=$(sudo grep '^BASEX_ADMIN_PASSWORD=' /root/basex-info.txt | cut -d= -f2-)
curl -ks -u admin:"$BASEX_PW" --get --data-urlencode \
'query=db:get("library")//book[xs:integer(year) gt 2010]/title/string()' \
https://127.0.0.1/rest/library

Step 9: Retrieve and export data over REST
The REST API retrieves resources and runs ad hoc queries. GET /rest/<database> returns the stored document, and GET /rest lists every database, so you can export content or drive BaseX from any HTTP client or script.
BASEX_PW=$(sudo grep '^BASEX_ADMIN_PASSWORD=' /root/basex-info.txt | cut -d= -f2-)
curl -ks -u admin:"$BASEX_PW" https://127.0.0.1/rest
curl -ks -u admin:"$BASEX_PW" https://127.0.0.1/rest/library
The first call lists your databases; the second returns the full XML content of the library database.
Step 10: Enable a real TLS certificate
The appliance ships with a self signed certificate generated per VM. For production, point a DNS record at the VM and replace it with a CA signed certificate. With certbot you can obtain one and drop it into the nginx TLS paths.
sudo apt-get update && sudo apt-get install -y certbot
sudo certbot certonly --standalone -d your-domain.example.com
sudo cp /etc/letsencrypt/live/your-domain.example.com/fullchain.pem /etc/nginx/tls/basex.crt
sudo cp /etc/letsencrypt/live/your-domain.example.com/privkey.pem /etc/nginx/tls/basex.key
sudo systemctl reload nginx
Clients can then verify the certificate normally instead of using -k.
Persistence, first boot and updates
Database content lives on the dedicated data disk mounted at /var/lib/basex (the BaseX databases, the user store and logs under DBPATH=/var/lib/basex/data) and is captured into the image, so a VM launched from this image is ready immediately. The first boot service generates the per VM admin password, applies it to the database, regenerates the per VM TLS certificate and writes a root only info note, then disables itself so subsequent reboots are unaffected. The OS ships fully patched with unattended security upgrades enabled.

Support
Every cloudimg deployment includes 24/7 support with a 24 hour response SLA. Contact support@cloudimg.co.uk for help with deployment, configuration or scaling.
This is a repackaged open source software product with additional charges for cloudimg support services. BaseX is a trademark of its respective owner. All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.