Application Infrastructure Azure

Hasura GraphQL Engine (CE v2) on Ubuntu 24.04 on Azure User Guide

| Product: Hasura GraphQL Engine (CE v2) on Ubuntu 24.04 LTS on Azure

Overview

Hasura GraphQL Engine gives you an instant, realtime GraphQL API over a relational database, plus a web console for exploring your schema, composing queries and managing row and column permissions. The cloudimg image ships the free and open source Community Edition (the Apache-2.0 v2 engine, hasura/graphql-engine), run the officially supported way as the upstream container alongside a bundled PostgreSQL, orchestrated by Docker Compose under systemd and fronted by nginx. Both images are pinned by digest and captured into the VM, so your instance starts in seconds. A unique admin secret and a unique database password are generated for each VM on first boot, before the port is reachable, so the console and the GraphQL endpoint are locked down from the very first request. Backed by 24/7 cloudimg support.

Hasura is a trademark of its respective owner. This image is produced by cloudimg and is not affiliated with, endorsed by, or sponsored by Hasura. It ships only the free and open source Apache-2.0 v2 Community Edition engine; it does not ship Hasura v3 / DDN.

The Hasura console Browse Rows view showing live data served through the GraphQL-backed PostgreSQL database

What is included:

  • Hasura GraphQL Engine Community Edition v2.49.4 (the Apache-2.0 v2 engine), pinned by image digest
  • A bundled PostgreSQL 16 database, pinned by image digest, reachable only inside a private Docker network (never published to a host port)
  • Docker Engine (Docker CE) with the engine published to the loopback interface only, fronted by nginx on port 80
  • hasura.service, hasura-firstboot.service and nginx.service as systemd units, enabled and active on boot
  • A unique HASURA_GRAPHQL_ADMIN_SECRET and a unique PostgreSQL password generated per VM on first boot, never baked into the image
  • A clean, empty database on first boot: no default account, no shipped secret, no prior data
  • 24/7 cloudimg support

Prerequisites

An active Azure subscription, an SSH key pair, and a VNet plus subnet in the target region. Standard_B2s (2 vCPU / 4 GiB RAM) is a sensible starting point; increase the size for heavier workloads. NSG inbound: allow 22/tcp from your management network and 80/tcp (and 443/tcp once you add TLS) for the console and the GraphQL API. The engine serves plain HTTP on port 80; for production, put it behind TLS with your own domain (see the final section).

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Hasura GraphQL Engine 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 hasura \
  --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 hasura --port 80 --priority 1010

Step 3 - Connect to your VM

ssh azureuser@<vm-public-ip>

Step 4 - Confirm the services are running

On first boot the image generates a unique admin secret and database password, initialises a clean PostgreSQL database, and starts the engine. Confirm the systemd services are active and that both containers (the engine and the bundled PostgreSQL) are healthy:

systemctl is-active docker hasura nginx
docker ps --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}'

All three services report active, and both hasura-graphql-engine-1 and hasura-postgres-1 report healthy.

The engine and bundled PostgreSQL containers running and healthy under systemd

The engine is published to the loopback interface only and fronted by nginx; the bundled PostgreSQL is never exposed on a host port. The public liveness endpoint returns 200 with no credentials:

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

Step 5 - Secure by default: the admin secret gates everything

The engine ships locked down. Any request to an admin endpoint (metadata, run SQL, the console) without the exact per-VM admin secret is rejected with 401. Confirm it yourself - this request sends no secret:

curl -s -o /dev/null -w 'no secret: HTTP %{http_code}\n' \
  -X POST http://127.0.0.1/v1/metadata \
  -H 'Content-Type: application/json' \
  -d '{"type":"export_metadata","args":{}}'

It returns HTTP 401. The same is true for the GraphQL endpoint and the console: nothing is readable or writable without your admin secret.

Admin endpoints reject requests with no secret (401) and accept only the per-VM admin secret (200); health stays public

Your unique admin secret is written to /root/hasura-notes.txt, readable only by root:

sudo stat -c '%a %U:%G' /root/hasura-notes.txt

It reports 600 root:root. View the notes (which include your admin secret, the console URL and the GraphQL endpoint) with:

sudo cat /root/hasura-notes.txt

The per-VM access notes, with the admin secret and database password masked

Step 6 - Open the console

Browse to http://<vm-public-ip>/console. The console prompts for your admin secret before it loads anything - this is the gate that protects your database.

The Hasura console admin secret prompt - nothing loads until the per-VM secret is entered

Paste the admin secret from /root/hasura-notes.txt and select Enter. The console opens on the API tab with GraphiQL, where you can compose and run GraphQL queries, mutations and subscriptions against your data, and browse the auto-generated schema in the Explorer panel.

The GraphiQL API explorer, with the admin secret header set and the auto-generated GraphQL schema in the Explorer

The Data tab manages your database: connect schemas, create and track tables, define relationships and set permissions. The bundled database is reported here as PostgreSQL 16.

The Data Manager showing the bundled PostgreSQL 16 database connected to the engine

Step 7 - Call the GraphQL API from the command line

Every request to the GraphQL endpoint must carry your admin secret in the x-hasura-admin-secret header. The block below reads the secret from your notes file (so it never appears on screen) and runs a GraphQL query that confirms the endpoint is authenticated and serving:

S=$(sudo grep '^HASURA_ADMIN_SECRET=' /root/hasura-notes.txt | cut -d= -f2-)
curl -s -X POST http://127.0.0.1/v1/graphql \
  -H "x-hasura-admin-secret: $S" \
  -H 'Content-Type: application/json' \
  -d '{"query":"query { __typename }"}'

It returns {"data":{"__typename":"query_root"}}, proving an authenticated GraphQL round trip against the bundled PostgreSQL. Once you create and track a table (for example a products table) in the Data tab, Hasura instantly exposes it as GraphQL. From your own machine, substitute your VM public IP and your admin secret:

curl -X POST http://<vm-public-ip>/v1/graphql \
  -H 'x-hasura-admin-secret: <HASURA_ADMIN_SECRET>' \
  -H 'Content-Type: application/json' \
  -d '{"query":"query { products { id name category price in_stock } }"}'

A GraphQL query returning live rows from a tracked table over the bundled PostgreSQL

Step 8 - Rotate the admin secret

The admin secret is your master key. To set your own, edit the environment file and restart the engine:

sudo sed -i 's/^HASURA_GRAPHQL_ADMIN_SECRET=.*/HASURA_GRAPHQL_ADMIN_SECRET=<your-new-secret>/' /etc/hasura/hasura.env
sudo systemctl restart hasura

Step 9 - Production: your own domain with TLS

For production, front the engine with your own domain and TLS. Point a DNS record at the VM public IP, then install a certificate with your preferred tool (for example Certbot with the nginx plugin) and reload nginx. Restrict inbound access in your NSG to 443/tcp (and 22/tcp from your management network) once TLS is in place, and keep the admin secret confidential - it grants full read and write access to your database.

Support

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