Deployment guide

Pluto.jl

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. 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.

This SecureAnyCloud 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.

What you get:

  • 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 and never exposed directly to the network
  • A reactive welcome notebook preloaded under /var/lib/pluto/notebooks
  • pluto.service and 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 SecureAnyCloud support

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.

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 reasonable starting point for interactive notebooks. Step up to a larger size for heavier numerical work.

Configure the network security group (NSG) to allow inbound 22/tcp from your management network and 80/tcp. Pluto serves plain HTTP on port 80, so 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 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). 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:pluto-jl-ubuntu-24-04:default:latest
az vm create \
  --resource-group <your-rg> \
  --name pluto \
  --image sac1647283583153:pluto-jl-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 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. Check the listeners:

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

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. Read it with:

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.

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 suitable for an Azure Load Balancer health probe.

Step 7 - Confirm the login password is enforced

A password is set on first boot, so an unauthenticated request to the notebook UI is rejected with HTTP 401. 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 command prints 200.

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.

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, because 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.

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 and squares becomes [1, 4, 9, 16, 25, 36, 49, 64]. The summary updates to say that the squares sum to 204.

This 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.

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.

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) for production use.
  • Security patches: unattended-upgrades remains enabled, so the OS continues to receive security updates automatically.
  • License: Pluto.jl and Julia are both MIT licensed. This image ships the open source Pluto. The SecureAnyCloud charge covers packaging, security patching, image maintenance and support.

Support

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

Deploy on Azure

Launch Pluto.jl 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