Deployment guide

Aim

Overview

Aim is an open-source ML experiment tracker. Your training code logs metrics, hyperparameters and other artifacts as it runs, and Aim's fast web UI lets you browse, filter and compare those runs afterwards. It is a self-hosted alternative to hosted experiment trackers.

This SecureAnyCloud image installs the pinned official Aim 3.29.1 pip package into a dedicated virtual environment and runs the built-in web UI and API server (aim up) under systemd. Aim itself is bound to loopback only, and nginx handles all customer-facing traffic on port 80 behind a per-VM HTTP Basic Auth gate. Aim has no user accounts of its own, so the nginx Basic Auth credential (user admin, with a unique password generated on first boot) is the gate on the UI and REST API.

What you get:

  • Aim 3.29.1 installed via pip into a dedicated virtual environment, running as the aim systemd service
  • The Aim web UI and full REST API on :80, fronted by nginx with Aim bound to loopback only
  • Per-VM HTTP Basic Auth (user admin) protecting the UI and API, with a unique password generated on first boot
  • A dedicated 20 GiB Azure data disk at /var/lib/aim holding the Aim repository, the actual experiment database (RocksDB-backed, durable across restarts and reboots)
  • A seeded demo experiment (sac-demo, 3 runs with varying hyperparameters and metric curves), so the runs table, metrics chart, run detail and hyperparameters views show real data on first login
  • aim.service and nginx.service as enabled, active systemd units
  • An unauthenticated /healthz endpoint on :80 for Azure Load Balancer health probes
  • 24/7 SecureAnyCloud support

Prerequisites

You need an active Azure subscription, an SSH key pair, and a VNet with a subnet in the target region.

Standard_B2s (2 vCPU / 4 GiB RAM) is a comfortable starting size for a small team's experiment tracking. Choose a larger size for bigger repositories or heavier UI concurrency.

Configure the network security group (NSG) to allow inbound 22/tcp from your management network, 80/tcp for the UI and API, and 443/tcp if you add TLS. Aim serves plain HTTP, so for production terminate TLS in front of it with your own domain.

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Aim by SecureAnyCloud, and select Create.

On the Basics tab, 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).

Review the dedicated data disk on the Disks tab, then select Review + create and Create.

Step 2 - Deploy from the Azure CLI

# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:aim-ubuntu-24-04:default:latest
az vm create \
  --resource-group <your-rg> \
  --name aim \
  --image sac1647283583153:aim-ubuntu-24-04:default:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_ed25519.pub \
  --vnet-name <your-vnet> --subnet <your-subnet> \
  --public-ip-sku Standard
az vm open-port --resource-group <your-rg> --name aim --port 80 --priority 1010

Step 3 - Connect to your VM

ssh azureuser@<vm-public-ip>

Step 4 - Confirm the services are running

systemctl is-active aim.service nginx.service

Both services report active. Aim serves its web UI and full REST API on the loopback address 127.0.0.1:43800 only. nginx fronts port 80 with the per-VM HTTP Basic Auth gate.

The Aim repository lives on the dedicated data disk at /var/lib/aim. It is the actual experiment database (RocksDB-backed), not just a log file, so it survives service restarts and VM reboots.

Step 5 - Retrieve your web UI password

nginx protects the Aim UI and API with HTTP Basic Auth. The username is admin. Your VM generates a unique password on first boot and writes it to a root-only file. Read it with:

sudo cat /root/aim-credentials.txt

The file contains AIM_USERNAME, AIM_PASSWORD, the AIM_URL to open in a browser, and AIM_REPO_PATH for pointing your own training scripts at this server's repository.

The password is stored on disk only as a bcrypt hash in /etc/nginx/.aim.htpasswd, so no plaintext password ships in the image. Keep a copy of the password somewhere safe.

Step 6 - Confirm the health endpoint

nginx serves an unauthenticated health endpoint for load balancers and probes. Request it with:

curl -s http://localhost/healthz

The endpoint returns ok. It never requires authentication, so you can use it for an Azure Load Balancer health probe.

Step 7 - Confirm authentication and query the demo experiment

Because the VM sets a password on first boot, an unauthenticated request to the UI returns HTTP 401. Nobody can reach your experiment data without the password.

The following commands read the per-VM password from the credentials file, prove the authentication round trip, and list the demo experiment through the authenticated API:

PW=$(sudo grep '^AIM_PASSWORD=' /root/aim-credentials.txt | cut -d= -f2-)
echo "unauth : $(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1/)"
echo "wrongpw : $(curl -s -o /dev/null -w '%{http_code}' -u admin:wrong-pw http://127.0.0.1/)"
echo "authed : $(curl -s -o /dev/null -w '%{http_code}' -u admin:$PW http://127.0.0.1/)" curl -s -u admin:$PW http://127.0.0.1/api/experiments/ | python3 -m json.tool

The output shows unauth : 401, wrongpw : 401 and authed : 200. The API response lists the sac-demo experiment with run_count: 3. Only the per-VM password reaches the Aim UI and API, because Aim is bound to loopback and nginx on port 80 is the only way in.

Step 8 - Sign in and browse the runs table

Browse to http://<vm-public-ip>/. When your browser prompts for credentials, enter admin and the password from Step 5.

Aim opens on the Runs explorer. It lists the three demo runs seeded on first boot (baseline-lr1e-3, higher-lr3e-3, sgd-momentum). Each run is logged against the sac-demo experiment with its own hyperparameters and metric history.

Step 9 - Compare metrics across runs

Open Metrics from the left navigation and click + Metrics. Select the tracked metrics you want to compare (for example loss subset="train" and accuracy subset="train"), then click Search.

Aim plots each selected metric as a chart with one line per run. You can see at a glance which hyperparameter combination trained faster or reached a better result.

Step 10 - Inspect a single run's detail

Click a run to open its detail view. The Overview tab shows the run's hyperparameters (hparams.learning_rate, hparams.batch_size, hparams.optimizer), description and metadata.

The Metrics, System and other tabs along the top show that run's individual metric curves, its system resource usage during training, and any logged images, text or figures.

Step 11 - Compare hyperparameters across runs

Open Params from the left navigation and click + Run Params. Select the hyperparameters you want to compare (hparams.batch_size, hparams.learning_rate, hparams.optimizer), then click Search.

Aim renders a parallel-coordinates plot alongside a table with a Tags column. You can see at a glance which hyperparameter combinations your runs used.

Step 12 - Log your own training runs

Point your own training code at this server's repository. If your training job runs on the same VM, or has the repository mounted over a shared filesystem, use the Aim Python SDK directly:

from aim import Run run = Run(repo="/var/lib/aim", experiment="my-experiment") run["hparams"] = {"learning_rate": 0.0003, "batch_size": 64, "optimizer": "adamw"} for step, (loss, acc) in enumerate(your_training_loop()): run.track(loss, name="loss", step=step, context={"subset": "train"}) run.track(acc, name="accuracy", step=step, context={"subset": "train"}) run.close()

Run pip install aim==3.29.1 in your training environment to match the server's SDK version.

If training runs on a different host and cannot reach this server's filesystem, use Aim's remote tracking server (aim server). It is a separate feature that this appliance does not enable by default. See the upstream Aim documentation for the remote-tracking setup.

Maintenance

  • Password. The UI and API password is set on first boot and stored as a bcrypt entry in /etc/nginx/.aim.htpasswd. To change it, run sudo htpasswd -B /etc/nginx/.aim.htpasswd admin, then sudo systemctl reload nginx.
  • Durable storage. The Aim repository (/var/lib/aim/.aim) survives aim service restarts and VM reboots. If your experiment history matters, back up or snapshot the data disk as you would any production database.
  • Restrict access. Aim serves plain HTTP on port 80. In your NSG, restrict access to trusted IP ranges, and front Aim with TLS terminating on :443 (for example, certbot with your own domain).
  • Loopback binding. Aim is bound to 127.0.0.1:43800 in /etc/systemd/system/aim.service (--host 127.0.0.1 --port 43800), so nginx is the only path in. Do not change the bind address to a public interface.
  • Disk space. The Aim repository grows with the number of runs and metrics you log. Monitor /var/lib/aim usage (df -h /var/lib/aim) and resize the data disk if you log at high volume or run long projects.
  • Logs. journalctl -u aim shows recent Aim server output. journalctl -u nginx shows the web server's own logs.
  • Security patches. unattended-upgrades stays enabled, so the OS keeps receiving security updates automatically.

Support

SecureAnyCloud provides 24/7 expert support for this image. Contact sales@secureanycloud.com.

Deploy on Azure

Launch Aim ML Experiment Tracking on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure