Girder on Ubuntu 24.04 on Azure User Guide
Overview
Girder is Kitware's free, open source, web based data management platform. It gives research groups, imaging labs and data engineering teams one place to store, organise, share and serve large collections of files: data is arranged in a hierarchy of collections, folders, items and files, any object can carry searchable metadata, and access is controlled per user and per group. Everything the web interface does is also a documented REST call, so ingest, reporting and instance-to-instance mirroring can be fully scripted. The cloudimg image delivers Girder fully installed and configured on Ubuntu 24.04 with MongoDB 8.0, a background task worker and an nginx front end, plus a filesystem assetstore provisioned on first boot so uploads work immediately. Backed by 24/7 cloudimg support.
Girder is licensed under the Apache License 2.0 (Copyright Kitware, Inc.). All product and company names are trademarks or registered trademarks of their respective holders. This image repackages the upstream open source release with cloudimg's provisioning and support.
What is included:
- Girder 5.0.14 (Apache-2.0) running as an ASGI application under
uvicornon127.0.0.1:8080 - nginx on port 80 as the public front end, configured with the WebSocket and streaming-upload settings Girder documents
- MongoDB 8.0 as the application database, bound to the loopback interface with authentication enabled
- A
girder-workerbackground task service (with a loopback Redis broker) so collection and folder deletion, folder copying and assetstore imports all work - A filesystem assetstore provisioned at
/var/lib/girder/assetstoreon first boot, so the platform is usable the moment it comes up - A per-VM administrator password and a per-VM MongoDB password, both generated on first boot and written to a root-only file, so no default or shared login ships in the image
mongod.service,redis-server.service,girder.service,girder-worker.serviceandnginx.serviceas systemd units, enabled and active- 24/7 cloudimg support

Prerequisites
An active Azure subscription, an SSH key pair, and a VNet plus subnet in the target region. Standard_B2s (2 vCPU / 4 GiB RAM) is a good starting point; scale up for larger catalogues, many concurrent users or heavy upload volumes. NSG inbound: allow 22/tcp from your management network and 80/tcp (HTTP) from your users. Add 443/tcp if you enable HTTPS. MongoDB and Redis listen on localhost only, so no database or broker port is exposed. Data written through the filesystem assetstore lives on the OS disk, so choose a disk size that suits the volume of data you intend to store, or add an Amazon S3 assetstore (Step 9).
Step 1 — Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Girder by cloudimg, and select Create. On Basics pick your subscription, resource group, region and size; under Administrator account choose SSH public key and paste your key; under Inbound port rules allow SSH (22) and HTTP (80). Then Review + create and Create.
Step 2 — Deploy from the Azure CLI
az vm create \
--resource-group <your-rg> \
--name girder \
--image <marketplace-image-urn> \
--size Standard_B2s \
--admin-username azureuser \
--generate-ssh-keys \
--public-ip-sku Standard
Open HTTP to reach the web interface:
az vm open-port --resource-group <your-rg> --name girder --port 80 --priority 900
Step 3 — Connect to your VM
ssh azureuser@<vm-public-ip>
Step 4 — Retrieve the first-boot administrator credentials
On the first boot of your instance, girder-firstboot.service generates a fresh MongoDB password, enables database authentication, creates a single site administrator with a random password and provisions the filesystem assetstore, writing everything to a root-only file. Read it with:
sudo cat /root/girder-credentials.txt
You will see the instance URL, the administrator login and password, and the MongoDB user and password. These values are unique to this VM and are not stored anywhere else, so save the administrator password somewhere safe.

Step 5 — Confirm the services are healthy
The database, broker, application server, task worker and web server are managed by systemd and come up on boot. Confirm they are active:
systemctl is-active mongod redis-server girder girder-worker nginx
Check that the REST API answers and reports the Girder release:
curl -s http://127.0.0.1/api/v1/system/version | python3 -m json.tool


Step 6 — Sign in to the web interface
Browse to http://<vm-public-ip>/ and choose Log In in the top right. Enter the administrator login and password from Step 4. You arrive at the Collections view, which is the top of Girder's data hierarchy. A fresh instance has no collections yet, and the left-hand navigation gives you Collections, Groups, Users, My Folders and the Admin console.

Step 7 — Create a collection and upload data
Click Create collection, give it a name and description, and choose whether it is public. Open the collection and use the folder button to create folders inside it, then use the green upload button to add files. Girder stores each uploaded file as an item containing one or more files, and shows sizes, download and preview actions for every row. Select a folder or item and open the Metadata panel to attach arbitrary key/value metadata, which is indexed and searchable from the header search box.

Step 8 — Drive Girder from the REST API
Every operation in the interface is a REST call, documented interactively at http://<vm-public-ip>/api/v1. Authenticate with HTTP Basic to obtain a token, then pass it as the Girder-Token header. This example reads the administrator password straight from the root-only credentials file, so you can paste it as-is:
PASS=$(sudo grep '^girder.admin.pass=' /root/girder-credentials.txt | cut -d= -f2-)
TOKEN=$(curl -s -u "admin:$PASS" http://127.0.0.1/api/v1/user/authentication \
| python3 -c 'import json,sys; print(json.load(sys.stdin)["authToken"]["token"])')
curl -s -H "Girder-Token: $TOKEN" "http://127.0.0.1/api/v1/collection?limit=0" \
| python3 -c 'import json,sys; [print(c["name"]) for c in json.load(sys.stdin)]'
Creating a collection and a folder from the API follows the same pattern:
PASS=$(sudo grep '^girder.admin.pass=' /root/girder-credentials.txt | cut -d= -f2-)
TOKEN=$(curl -s -u "admin:$PASS" http://127.0.0.1/api/v1/user/authentication \
| python3 -c 'import json,sys; print(json.load(sys.stdin)["authToken"]["token"])')
COLLECTION_ID=$(curl -s -H "Girder-Token: $TOKEN" -X POST \
--data-urlencode "name=API Example" --data-urlencode "description=Created from the REST API" \
http://127.0.0.1/api/v1/collection | python3 -c 'import json,sys; print(json.load(sys.stdin)["_id"])')
echo "collection id: $COLLECTION_ID"
For bulk transfers, Kitware also publishes an official Python client (pip install girder-client) that wraps the same API.
Step 9 — Assetstores: where the bytes actually live
Girder separates the catalogue from the storage behind it. The image provisions a filesystem assetstore at /var/lib/girder/assetstore and marks it current, so uploads work with no setup. Review it from the API:
PASS=$(sudo grep '^girder.admin.pass=' /root/girder-credentials.txt | cut -d= -f2-)
TOKEN=$(curl -s -u "admin:$PASS" http://127.0.0.1/api/v1/user/authentication \
| python3 -c 'import json,sys; print(json.load(sys.stdin)["authToken"]["token"])')
curl -s -H "Girder-Token: $TOKEN" http://127.0.0.1/api/v1/assetstore \
| python3 -c 'import json,sys; [print("name=%s type=%s current=%s root=%s" % (a["name"], a["type"], a["current"], a.get("root"))) for a in json.load(sys.stdin)]'

In the web interface, open Admin console then Assetstores to see capacity, add a second filesystem assetstore, or add an Amazon S3 assetstore for object storage. Setting a different assetstore as current changes where new uploads are written; existing files stay where they are. Import data pulls files that already exist in an assetstore into the Girder hierarchy without copying them.

Security model
This image ships with no login, no database credential and no data. Girder itself has no built-in accounts, and its API refuses to grant administrator rights to a self-registered user, so the only administrator that can ever exist is the one first boot creates. Both girder.service and nginx.service are held offline until first boot has finished, so the platform is never reachable before its administrator exists. A wrong password is rejected; only the generated per-VM password authenticates:
PASS=$(sudo grep '^girder.admin.pass=' /root/girder-credentials.txt | cut -d= -f2-)
curl -s -o /dev/null -w "wrong password -> HTTP %{http_code}\n" \
-u "admin:WrongGuess-123" http://127.0.0.1/api/v1/user/authentication
curl -s -o /dev/null -w "per-VM password -> HTTP %{http_code}\n" \
-u "admin:$PASS" http://127.0.0.1/api/v1/user/authentication
A wrong password returns HTTP 401; the correct per-VM password returns HTTP 200 with an authentication token. MongoDB runs with authentication enabled and is bound to the loopback interface, so it cannot be reached from the network at all:
sudo ss -tln | grep -E '27017|6379'
Both the database and the Redis task broker listen only on 127.0.0.1.
Close self-registration
Girder ships with its upstream default registration policy of open, so anyone who can reach the instance can create an ordinary account. Self-registered users never receive administrator rights and see only public data, but on an internet-facing deployment you will usually want registration closed. In the web interface open Admin console then Server configuration, set Registration policy to Closed and save. From then on only an administrator can create accounts, from Admin console then Users.
Enable HTTPS with a custom domain
Point a DNS A record at your VM's public IP, allow 443/tcp in the NSG, then install a certificate with Certbot. Certbot edits the nginx site in place and keeps the proxy settings Girder needs:
sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.example.com
Girder's web client calls the API on the same origin it was served from, so no application setting has to change when you move to HTTPS.
Maintenance
- Logs:
journalctl -u girderfor the application server,journalctl -u girder-workerfor background tasks,/var/log/nginx/for the web server and/var/log/mongodb/mongod.logfor the database. - Database backups: dump the catalogue with
sudo mongodump --uri "$(sudo grep '^GIRDER_MONGO_URI=' /etc/girder/girder.env | cut -d= -f2-)" --out /var/backups/girder, and back up/var/lib/girder/assetstorealongside it — the catalogue and the file content are both needed to restore. - Storage: the filesystem assetstore grows on the OS disk. Attach and mount a data disk, or add an Amazon S3 assetstore, before you approach the disk limit.
- OS updates: unattended security upgrades are enabled, so the base OS keeps patching itself.
- Restarting:
sudo systemctl restart girder girder-workerafter any configuration change in/etc/girder/girder.env.
Support
cloudimg provides 24/7 technical support for this Girder image by email (support@cloudimg.co.uk) and live chat, covering deployment, first-boot credentials, collections and folders, access control and groups, filesystem and Amazon S3 assetstores, the REST API and Python client, HTTPS setup, MongoDB administration and backups, and upgrades. For billing or subscription questions, contact support@cloudimg.co.uk.