Media & Entertainment Azure

OpenCue on Ubuntu 24.04 on Azure User Guide

| Product: OpenCue on Ubuntu 24.04 LTS on Azure

Overview

OpenCue is the open source render management system that turns a pile of machines into a render farm. Artists and pipeline tools submit a job made of layers and frames; OpenCue's scheduler, Cuebot, decides which render node runs which frame, when, with how many cores and how much memory. It tracks every frame through the queue, retries the ones that fail, keeps the logs, and reports what the farm is doing in real time. Originally built and run in production at Sony Pictures Imageworks and now an Academy Software Foundation project, it is designed around the way real productions work: shows, shots and departments, allocations and subscriptions that decide who gets the cores, per service memory and core minimums, and job dependencies.

The cloudimg image ships a complete, working single node farm on one VM. Cuebot, its PostgreSQL database, a render node daemon (RQD), the OpenCue REST gateway and the CueWeb browser interface are all installed, wired together and running when first boot finishes, so you can sign in and submit a job straight away, then add your own render nodes as the farm grows. Everything is pinned to the OpenCue v1.19.1 release and verified by checksum at install time.

Upstream publishes six default secrets across its sample configuration, including a sample signing key, and none of them exists on this image: every one is regenerated uniquely on each VM at first boot, and no OpenCue service is allowed to start until that has happened. The CueWeb interface, which upstream ships with no login at all, is placed behind a per VM credential. Backed by 24/7 cloudimg support.

OpenCue is a project of the Academy Software Foundation. This image is produced by cloudimg and is not affiliated with, endorsed by, or sponsored by the Academy Software Foundation, the OpenCue project or Sony Pictures Imageworks. It ships only the Apache-2.0 licensed open source OpenCue release.

The CueWeb job monitor showing one render job in progress and a completed job at three of three frames

What is included:

  • OpenCue 1.19.1: Cuebot (the scheduler and dispatcher, gRPC on port 8443), pinned to the release jar and verified by SHA-256
  • PostgreSQL 16 as Cuebot's database, loaded with the OpenCue schema and seed data and bound to the loopback interface
  • RQD 1.19.1 (openrqd, the render node daemon) running on the same VM, so the farm can execute frames out of the box
  • The OpenCue REST gateway, built from the pinned v1.19.1 source, confined to loopback peers by a kernel level systemd IP filter
  • CueWeb, the browser interface, built from the pinned v1.19.1 source and fronted by nginx on port 80 with HTTP Basic authentication
  • The OpenCue client tools cueadmin, cueman and pycuerun pinned to 1.19.1, plus opencue-submit-demo and opencue-job-status helpers
  • cuebot.service, openrqd.service, opencue-rest-gateway.service, cueweb.service, nginx.service and opencue-firstboot.service as systemd units, enabled and active on boot
  • A unique web interface password, a unique database password, a unique database superuser password, a unique REST gateway signing key and a unique CueWeb session secret, all generated per VM on first boot and never baked into the image
  • A clean, freshly seeded database on first boot: no default login, no shipped secret, no prior jobs or render hosts
  • 24/7 cloudimg support

Prerequisites

An active Azure subscription, an SSH key pair, and a VNet plus subnet in the target region. Standard_B2ms (2 vCPU / 8 GiB RAM) is the recommended size and the smallest that works properly: OpenCue's own seeded service definitions reserve 3.2 GiB of memory per frame for the default and shell services, so a 4 GiB VM cannot book a default frame while also running the scheduler. Size up for more concurrent frames, or keep this VM as the scheduler and add dedicated render nodes.

NSG inbound: allow 22/tcp from your management network and 80/tcp (and 443/tcp once you add TLS) for the web interface. If you plan to add render nodes or connect the CueGUI desktop client, also allow 8443/tcp and 8444/tcp from your render network only - OpenCue's gRPC farm protocol is unauthenticated by design, so those two ports must never be open to the internet.

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for OpenCue 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 opencue \
  --image <marketplace-image-urn> \
  --size Standard_B2ms \
  --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 opencue --port 80 --priority 1010

Step 3 - Connect to your VM

ssh azureuser@<vm-public-ip>

Step 4 - Confirm the farm is running

On first boot the image generates every per VM secret, seeds a clean database and starts the whole stack. Confirm the six services are active:

systemctl is-active postgresql cuebot openrqd opencue-rest-gateway cueweb nginx

Each one reports active. The public liveness endpoint answers with no credential:

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

That returns health: HTTP 200. Only two ports are meant to leave the VM: 80 (the authenticated web interface) and, if you add render nodes, the farm ports 8443 and 8444. The database, the CueWeb application server and Cuebot's metrics port stay on the loopback interface:

ss -ltn | grep -E ':(80|3000|5432|8080|8443|8444|8448)\b'

The six OpenCue services reporting active, the liveness endpoint returning 200, and the listening sockets showing the database and web application bound to loopback

The REST gateway on 8448 binds all interfaces upstream and cannot be told otherwise, so its systemd unit carries a kernel level IP filter (IPAddressDeny=any with IPAddressAllow=localhost) that drops every non loopback peer. A connection to it from any address other than 127.0.0.1 simply never completes.

Step 5 - Secure by default: the credential gates everything

CueWeb can pause, kill and retry any job on the farm, so it is never left open. cloudimg fronts it with nginx HTTP Basic authentication using a password generated uniquely for this VM on first boot, before the port was ever reachable. Any request without the exact credential is rejected. Confirm it yourself - this request sends none:

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

It returns no credential: HTTP 401. Guessable defaults are rejected too:

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

Your unique credential authenticates and returns 200. The block below reads the password from the credentials file, so it never appears on screen:

P=$(sudo grep '^OPENCUE_UI_PASSWORD=' /root/opencue-credentials.txt | cut -d= -f2-)
curl -s -o /dev/null -u "<OPENCUE_UI_USER>:$P" -w 'per-VM credential: HTTP %{http_code}\n' http://127.0.0.1/

The credentials file is readable only by root:

sudo stat -c '%a %U:%G' /root/opencue-credentials.txt

It reports 600 root:root. View it - it holds the web interface user and password, the database passwords, the REST gateway signing key and the CueWeb session secret, all unique to this VM:

sudo cat /root/opencue-credentials.txt

The web interface rejecting no credential and admin:admin with 401 and accepting the per-VM credential with 200, alongside the root-only credentials file listing every per-VM secret

Step 6 - Inspect the render farm

cueadmin is the OpenCue administration CLI. List the render hosts registered with Cuebot - the bundled node reports itself on first boot and should be UP:

cueadmin -lh

The host line shows its cores, memory, the allocation it landed in (local.general) and its state. List the allocations, which are how you partition the farm between facilities and machine classes:

cueadmin -la

And list the shows, which are the top level unit of work in OpenCue. The image seeds one show, testing, so you have somewhere to submit to immediately:

cueadmin -ls

cueadmin listing the registered render host reporting UP with two cores, the farm allocations, and the seeded show

Step 7 - Submit a real job to the farm

The image ships a small demo outline that submits three frames of shell work. Run it:

opencue-submit-demo

It prints the job name it launched. Cuebot will not accept a second job with the same name while the first is still pending, so let a run finish before submitting the demo again. Cuebot books the frames onto the render node within a few seconds; list them with cueman and each one shows the render host it was dispatched to and how long it has been running:

sleep 10
cueman -lf testing-demo-opencue_hello_farm

Once the farm has finished, the job leaves the live queue, so use the status helper, which includes finished jobs:

sleep 45
opencue-job-status testing-demo-opencue_hello_farm

It reports succeeded: 3 of 3 total. Every frame's output is captured to a render log on disk, exactly as it would be for a real render. Wait for the first frame's log to appear, then read it:

for i in $(seq 1 30); do
  L=$(sudo ls -t /var/log/opencue/frames/testing/demo/logs/*/*.0001-render.rqlog 2>/dev/null | head -1)
  [ -n "$L" ] && break
  sleep 5
done
sudo grep -m1 -A2 'rendering frame' "$L"

Submitting the demo job, cueman showing frames dispatched to the render host, the job completing three of three frames, and the render log capturing the frame command output

Step 8 - Open the CueWeb interface

Browse to http://<vm-public-ip>/. Your browser prompts for the credential; enter the user <OPENCUE_UI_USER> and the password from /root/opencue-credentials.txt.

CueWeb opens on the job monitor. It starts empty by design - you choose which jobs to watch. Type a show-shot- prefix such as testing-demo- into the search box and pick the job from the list to add it to the monitor. Each row shows the job state, frames done out of total, start and finish times, and a colour coded progress bar: green for succeeded, yellow for running, blue for waiting.

The CueWeb job monitor showing a render in progress with running and waiting frames alongside a completed job at three of three

Step 9 - Drill into layers and frames

Select the open-in-new icon at the end of a job row to open its breakdown. The upper table lists the job's layers with the service each one uses, its frame range, and the cores, memory and GPU it reserves per frame. The lower table lists every frame with its status, the render host it was dispatched to, retry count and runtime - this is where you watch a render progress frame by frame.

The CueWeb job breakdown showing the layer's service, frame range and memory reservation above a frame table with two frames running on the render host and four waiting

Step 10 - Read a frame's render log

Select a frame's layer link to open the frame page. It shows the frame's full record - host, cores, runtime, memory high water mark - above the render log streamed straight from disk, with a version selector when a frame has been retried. This is how you diagnose a failed render without logging into the render node.

The CueWeb frame page showing the frame running on the render host above its live render log

Step 11 - Control the queue

Select one or more jobs with the row checkboxes to enable the queue actions in the toolbar: pause and unpause a job, kill it, or eat and retry its dead frames. These are the day to day controls a wrangler uses to keep a farm moving.

The CueWeb job monitor with a job selected and the pause, unpause, kill, eat dead frames and retry dead frames actions available

Step 12 - Submit your own outlines

Jobs are described in Python with pyoutline. A minimal outline creates an Outline for a show and shot, adds one or more Shell layers with a frame range, and launches it. The demo that ships with the image is at /opt/opencue/examples/hello_farm.py and is a good starting point:

cat /opt/opencue/examples/hello_farm.py

Two things decide whether a frame will ever be dispatched, and both are worth knowing before you write your first outline:

  • Service tags must match the host. Each layer names a service (shell, default, maya, nuke, arnold and so on) and each service carries tags. A frame is only booked on a host whose allocation tag matches. The bundled node is tagged general, so the shell and default services work out of the box; preprocess and postprocess are tagged util and will wait forever until you tag a host for them.
  • Memory reservations are real. The seeded default, shell, arnold, houdini and prman services each reserve 3.2 GiB per frame. Set memory="256m" (or whatever your render actually needs) on the layer to override it, or the scheduler will hold frames until a host has that much free.

Submit an outline you have written with pycuerun, or run it directly with the bundled Python. Note that Cuebot refuses jobs submitted by root, so submit as your own user:

pycuerun /path/to/your_outline.py

Step 13 - Add render nodes

This VM is a complete farm on its own, but OpenCue is built to scale out. On each additional render machine install RQD from the same OpenCue release, point it at this VM's Cuebot with cuebot_endpoints: ["<this-vm-private-ip>:8443"] in its rqd.yaml, and start it. The node registers itself and appears in cueadmin -lh within a few seconds; from then on Cuebot dispatches frames to it automatically.

Keep 8443/tcp and 8444/tcp reachable only from your render subnet. OpenCue's farm protocol has no authentication of its own, so network scope is the control.

The CueGUI desktop client is not installed on this image, because a desktop application does not belong on a headless cloud VM. Install it on your own workstation from the same OpenCue release and point it at this VM's Cuebot endpoint if you prefer it to CueWeb.

Step 14 - Rotate the web interface password

The password is your access key to the farm. To set your own:

sudo htpasswd -B /etc/opencue/cueweb.htpasswd <OPENCUE_UI_USER>
sudo systemctl reload nginx

Step 15 - Production: your own domain with TLS

For production, front the web interface with your own domain and TLS. Point a DNS record at the VM public IP, install a certificate with your preferred tool (for example Certbot with the nginx plugin) and reload nginx. Once TLS is in place, restrict inbound access in your NSG to 443/tcp, plus 22/tcp from your management network and 8443/tcp and 8444/tcp from your render subnet only.

Keep the credential confidential: it grants full control of the queue, including the ability to kill running renders.

Support

This image is supported 24/7 by cloudimg. For help with deployment or configuration, contact support through cloudimg.co.uk.