Developer Tools Azure

Pluto.jl on Ubuntu 24.04 on Azure User Guide

| Product: Pluto.jl on Ubuntu 24.04 LTS on Azure

Overview

Pluto.jl is a reactive notebook environment for the Julia programming language. Unlike a traditional notebook that remembers whatever you ran in whatever order, Pluto builds a dependency graph of your cells: when you change a value, every cell that uses it re-runs immediately and automatically, and when you delete a cell its variables disappear with it. The result is a notebook with no hidden state, that always reflects the code in front of you, and that a colleague can open and reproduce exactly.

The cloudimg image ships Pluto as a ready-to-use notebook server, not a bare Julia install. A pinned Julia runtime and a pinned Pluto are installed and precompiled into the image, so the notebook UI answers quickly on first launch with no toolchain to assemble. Pluto runs as a systemd service bound to the loopback connector 127.0.0.1:1234 behind an nginx reverse proxy on port 80. nginx protects the whole app with HTTP Basic Auth, and a unique login password is generated on the first boot of every VM, so the notebook UI is never open to anonymous access. A small reactive welcome notebook ships with the image so you can see reactivity working the moment you sign in. Backed by 24/7 cloudimg support.

What is included:

  • Pluto.jl running as a systemd service (pluto.service), the reactive notebook server for Julia
  • A pinned Julia runtime with Pluto precompiled into the image for a fast first launch
  • The Pluto web UI on :80, fronted by nginx with HTTP Basic Auth (user admin)
  • A unique Basic Auth login password generated on first boot and recorded in a root-only file
  • Pluto bound to the loopback connector 127.0.0.1:1234 - never exposed directly to the network
  • A reactive welcome notebook preloaded under /var/lib/pluto/notebooks
  • pluto.service + nginx.service as systemd units, enabled and active
  • An unauthenticated /healthz endpoint for Azure Load Balancer health probes
  • A websocket-friendly nginx proxy configuration for Pluto's live cell updates
  • 24/7 cloudimg support

Prerequisites

An active Azure subscription, an SSH key pair, and a VNet + subnet in the target region. Standard_B2s (2 vCPU / 4 GiB RAM) is a reasonable starting point for interactive notebooks; step up to a larger size for heavier numerical work. NSG inbound: allow 22/tcp from your management network and 80/tcp. Pluto serves plain HTTP on port 80; for production, terminate TLS in front of it with your own domain and consider adding 443/tcp (see Maintenance).

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Pluto.jl 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 -> Create.

Step 2 - Deploy from the Azure CLI

az vm create \
  --resource-group <your-rg> \
  --name pluto \
  --image <marketplace-image-urn> \
  --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 pluto --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 pluto.service nginx.service

Both systemd units report active. Pluto (the Julia notebook server) is bound to the loopback connector 127.0.0.1:1234, and nginx fronts it on port 80 behind HTTP Basic Auth:

ss -tlnp | grep ':1234' | sed 's/users:.*//'

pluto.service and nginx.service active, with Pluto listening on the loopback connector 1234 and the pinned Julia runtime

Step 5 - Retrieve your login credentials

The appliance's network access gate is HTTP Basic Auth (user admin). The password is generated uniquely on the first boot of your VM and written to a root-only file:

sudo cat /root/pluto-credentials.txt

This file contains PLUTO_URL, PLUTO_USERNAME and PLUTO_PASSWORD. Store the password somewhere safe - it is the key to the reverse proxy gate in front of your notebooks.

The per-VM Pluto credentials file with the generated admin password and URL, unique to each VM

Step 6 - Confirm the health endpoint

nginx serves an unauthenticated health endpoint for load balancers and probes:

curl -s http://localhost/healthz

It returns ok. This endpoint never requires authentication, so it is safe for an Azure Load Balancer health probe.

Step 7 - Confirm the login password is enforced

Because a password is set on first boot, an unauthenticated request to the notebook UI is rejected (HTTP 401), so nobody reaches your notebooks without the password:

curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1/

It prints 401. A wrong password is also rejected with 401; only the per-VM password from Step 5 returns 200:

curl -s -o /dev/null -w '%{http_code}\n' -u 'admin:<PLUTO_PASSWORD>' http://127.0.0.1/

This prints 200.

nginx returning 401 for an unauthenticated request and 200 once the per-VM admin password is supplied, plus the built-in reactivity self-test confirming a dependent cell recomputes

Step 8 - Sign in to Pluto

Browse to http://<vm-public-ip>/. Your browser first prompts for HTTP Basic Auth credentials - enter admin and the password from Step 5. Behind that gate you reach the Pluto welcome page, where you can create a new notebook or open an existing one.

The Pluto welcome page behind the nginx Basic Auth gate, offering to create a new notebook or open one by path

Step 9 - Open the reactive welcome notebook

Under Open a notebook, enter the path /var/lib/pluto/notebooks/welcome.jl and select Open, then choose Run notebook code (Pluto opens a notebook in a safe preview first). The notebook runs and each cell shows its result: x = 3, y = 6 (because y = x * 2), and squares = [1, 4, 9]. The final line is a summary that reads its values from the cells above.

The reactive welcome notebook running: the code cells show their computed outputs and the summary reads the values from the cells above

Step 10 - See reactivity in action

Change x in the first cell - for example to 8 - and press Shift+Enter to run it. You do not touch any other cell, yet y immediately becomes 16, squares becomes [1, 4, 9, 16, 25, 36, 49, 64], and the summary updates to say the squares sum to 204. That automatic re-run of every dependent cell is Pluto's reactivity: the notebook has no hidden state, so what you see always matches the code.

After changing x to 8, every dependent cell has recomputed on its own: y is 16, squares runs to 64, and the summary reads sum 204

Step 11 - Create your own notebook

Return to the welcome page (the Pluto logo) and choose Create a new notebook to start from a blank canvas. Add a cell, type any Julia expression, and press Shift+Enter; add another cell that refers to a variable from the first, and watch it stay in step as you edit. Each notebook is saved as a plain .jl file under /var/lib/pluto/notebooks, so it reads as normal Julia source and works with version control.

The full reactive welcome notebook, top to bottom, served through the nginx Basic Auth gate

Step 12 - Confirm where your notebooks live

Your notebooks are stored on the VM under /var/lib/pluto/notebooks, owned by the unprivileged pluto service user:

sudo ls -l /var/lib/pluto/notebooks

The shipped welcome.jl is there; every notebook you create or open by path is saved alongside it.

Maintenance

  • Login password: the Basic Auth password in front of Pluto is set on first boot. To change it, run sudo sh -c 'printf "admin:%s\n" "$(openssl passwd -apr1 NEW_PASSWORD)" > /var/lib/pluto/.htpasswd' && sudo systemctl reload nginx.
  • Notebooks: your work lives under /var/lib/pluto/notebooks as plain .jl files - back up that directory to preserve your notebooks, and use git on it if you want version history.
  • Restarting Pluto: sudo systemctl restart pluto.service restarts the notebook server; open notebooks reconnect when you reload the page.
  • Julia packages: notebooks manage their own package environments inside the notebook file (Pluto's built-in package manager), so a notebook installs its own dependencies when it runs. The system-wide Julia lives under /opt/julia and its shared, precompiled depot is at /opt/julia/depot.
  • TLS: Pluto serves plain HTTP on port 80; front it with TLS (for example certbot with your own domain) before production use.
  • Security patches: unattended-upgrades remains enabled so the OS continues to receive security updates automatically.
  • License: Pluto.jl is MIT licensed and Julia is MIT licensed. This image ships the open source Pluto; the cloudimg charge covers packaging, security patching, image maintenance and support.

Support

cloudimg provides 24/7 expert support for this image. Contact support@cloudimg.co.uk.