Applications Azure

DOMjudge 9 on Ubuntu 24.04 on Azure User Guide

| Product: DOMjudge 9 on Ubuntu 24.04 LTS on Azure

Overview

DOMjudge is the widely-used, open source automated programming-contest control system behind ICPC-style contests, university courses and practice sessions. Contestants submit source code; a sandboxed judgehost compiles and runs each submission against secret test data and grades it automatically as accepted or rejected, while a live scoreboard tracks the standings. It ships separate interfaces for the jury/admin, for teams, and for public spectators, plus a full REST API.

The cloudimg image delivers DOMjudge 9.0.1 as a complete all-in-one appliance on Ubuntu 24.04: the Symfony/PHP domserver (served by nginx + PHP 8.3-FPM, backed by MariaDB) and a local judgehost (judgedaemon) preconfigured on a single VM, so a correct submission is graded end to end the moment it boots. A demo contest with example problems is pre-loaded so you can try a real submission straight away. Backed by 24/7 cloudimg support.

What is included:

  • DOMjudge 9.0.1 (GPL-2.0), built from the official release, installed under /opt/domjudge
  • Combined domserver + judgehost on one VM: nginx + PHP 8.3-FPM + MariaDB, plus the create-cgroups and domjudge-judgedaemon@0 services
  • A hardened judging sandbox: runguard runs untrusted contestant code inside a debootstrap chroot with cgroup v2 memory + CPU limits (no swap is baked into the image)
  • A pre-loaded demo contest with the example problems (hello, boolfind, fltcmp) and a demo team
  • Per-VM secrets generated at first boot — the web admin password, the judgehost REST credential, the demo team password, the MariaDB password and the Symfony APP_SECRET — with no default login; written to a root-only file
  • Health via the public scoreboard at /public and the REST API at /api/v4/
  • 24/7 cloudimg support

DOMjudge jury and admin sign-in page

Prerequisites

An active Azure subscription, an SSH key pair, and a VNet + subnet in the target region. Standard_B2ms (2 vCPU / 8 GiB RAM) is a good starting point for a small contest or a classroom; scale up, or attach additional dedicated judgehosts, for larger contests or higher submission volume (see Scaling the judge below). NSG inbound: allow 22/tcp from your management network and 80/tcp (plus 443/tcp once you enable HTTPS) from your users.

Step 1 — Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for DOMjudge by cloudimg, and select Create. On Basics pick your subscription, resource group, region and size (Standard_B2ms or larger); under Administrator account choose SSH public key and paste your key; under Inbound port rules allow SSH (22) and HTTP (80). Then Review + createCreate.

Step 2 — Deploy from the Azure CLI

az vm create \
  --resource-group <your-rg> \
  --name domjudge \
  --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 domjudge --port 80 --priority 1010

Step 3 — Connect to your VM

ssh azureuser@<vm-public-ip>

Step 4 — Confirm the services are running

DOMjudge runs as five systemd units — MariaDB, PHP-FPM and nginx (the domserver), plus create-cgroups and domjudge-judgedaemon@0 (the judgehost). They should all report active:

for u in mariadb php8.3-fpm nginx create-cgroups 'domjudge-judgedaemon@0'; do
  printf '%-28s %s\n' "$u" "$(systemctl is-active $u)"
done

DOMjudge services active

The public scoreboard answers on port 80 without authentication, and the REST API lists the contests:

curl -s -o /dev/null -w 'public scoreboard: HTTP %{http_code}\n' http://127.0.0.1/public
curl -s http://127.0.0.1/api/v4/contests | head -c 200; echo

DOMjudge version and health check

Step 5 — Retrieve your per-VM credentials

Every DOMjudge secret is regenerated uniquely on first boot — there is no default login. Read them (root only):

sudo cat /root/domjudge-credentials.txt

You will see the admin web password, the demo team password, the MariaDB password and the site URL. Store them somewhere safe.

Per-VM DOMjudge credentials generated at first boot

Step 6 — Sign in to the jury interface

Open http://<vm-public-ip>/ in a browser and sign in as admin with the password from the credentials file. The jury interface is where you manage contests, problems, teams, clarifications and judgings.

DOMjudge jury dashboard

Step 7 — Submit a solution and watch it get judged

The image ships a demo contest with the example hello problem and a demo team, so you can prove the autograder end to end immediately. Submit the shipped accepted solution over the REST API as the demo team (substituting the demo password from your credentials file):

ADMIN_PASS='<DOMJUDGE_ADMIN_PASSWORD>'
DEMO_PASS='<DOMJUDGE_DEMO_PASSWORD>'
SOL=/opt/domjudge/domserver/example_problems/hello/submissions/accepted/test-hello.c
SUBID=$(curl -s -u "demo:${DEMO_PASS}" \
  -F "problem=hello" -F "language=c" -F "code[]=@${SOL}" \
  http://127.0.0.1/api/v4/contests/demo/submissions | python3 -c 'import sys,json;print(json.load(sys.stdin)["id"])')
echo "submitted id=${SUBID}; waiting for the judgedaemon..."
for i in $(seq 1 40); do
  V=$(curl -s -u "admin:${ADMIN_PASS}" \
    "http://127.0.0.1/api/v4/contests/demo/judgements?submission_id=${SUBID}" \
    | python3 -c 'import sys,json;d=json.load(sys.stdin);print(d[-1].get("judgement_type_id") or "" if d else "")')
  [ -n "$V" ] && { echo "verdict: $V"; break; }
  sleep 3
done

A correct solution returns the verdict AC (accepted). In the jury interface the same submission shows a green CORRECT judging, with the compile result and per-testcase run times.

Submission judged CORRECT by the judgedaemon

The result appears on the public scoreboard at http://<vm-public-ip>/public:

Public scoreboard with the accepted solve

Over the REST API the judgement carries judgement_type_id: "AC":

Autograder verdict over the REST API

Step 8 — Run your own contest

From the jury interface you can create your own contest, import problems (DOMjudge accepts Kattis/ICPC problem-archive ZIPs), register teams and issue their passwords, then open the contest. The admin CLI is available for scripting:

sudo -u www-data /opt/domjudge/domserver/bin/dj_console list | grep domjudge

Reset a user's password from the CLI at any time:

sudo -u www-data /opt/domjudge/domserver/bin/dj_console domjudge:reset-user-password <username> <new-password>

The judging sandbox, memory limits and swap

The judgehost compiles and runs untrusted code inside a chroot with cgroup v2 resource limits enforced by runguard. This image deliberately ships with no swap (an Azure Marketplace image requirement); the per-submission memory limit is enforced directly by the memory controller, and a submission that exceeds it is stopped and reported as Memory Limit Exceeded — no swap device is needed. If you run contests with large per-submission memory limits and want the extra headroom of swap, enable it on Azure's ephemeral resource disk (managed by the Azure Linux Agent) rather than on the OS disk:

# /etc/waagent.conf
ResourceDisk.EnableSwap=y
ResourceDisk.SwapSizeMB=4096

Then sudo systemctl restart walinuxagent. This keeps the OS image swap-free while giving the judge swap on the throwaway resource disk.

Scaling the judge

A single VM runs the domserver and one judgehost, which is ample for classrooms and small contests. For larger contests, run the domserver on this VM and attach additional dedicated judgehosts: install the DOMjudge judgehost on separate VMs, point their restapi.secret at http://<domserver-ip>/api with the judgehost credential from /opt/domjudge/domserver/etc/restapi.secret, and they will pull and grade submissions in parallel. Give each judgehost its own CPU cores for consistent timing.

Enable HTTPS (recommended for public contests)

Put a TLS certificate in front of nginx. With a DNS name pointed at the VM:

sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.example.com

Maintenance

  • Back up the MariaDB database (domjudge) regularly — it holds every contest, submission and judging: sudo mysqldump domjudge | gzip > domjudge-backup.sql.gz
  • Security updates apply automatically via unattended-upgrades
  • Logs: sudo journalctl -u domjudge-judgedaemon@0 for the judge, and /opt/domjudge/domserver/webapp/var/log/ for the domserver

Support

Every cloudimg image includes 24/7 support. Contact us through the cloudimg website with your VM details and the output of the commands above.