Developer Tools Azure

Graphweaver on Ubuntu 24.04 on Azure User Guide

| Product: Graphweaver on Ubuntu 24.04 LTS on Azure

Overview

Graphweaver is an open-source, MIT-licensed framework that connects data sources and exposes them as a single, unified GraphQL API, with a rich admin dashboard generated automatically from your schema. You describe your data as typed entities backed by providers, and Graphweaver builds the queries, mutations, pagination and relationships for you, then serves a React admin user interface over the same API.

This cloudimg image ships a complete, self-contained demo appliance: a Graphweaver application backed by a bundled SQLite datastore that is seeded on build with a small Project and Task schema, so the GraphQL API answers real queries and the admin dashboard shows real data the moment it boots. It is a fast way to evaluate Graphweaver, prototype an internal tool, or learn how a schema maps to a live GraphQL API and admin interface. Backed by 24/7 cloudimg support.

What is included:

  • Graphweaver v2.23.1 (the @exogee/graphweaver family), built from the published packages into a standalone GraphQL backend (dist/backend) and a static admin UI (dist/admin-ui)
  • A bundled SQLite datastore seeded with a demo Project + Task schema — no external database, no MongoDB, no Redis
  • The backend running as graphweaver.service on the loopback interface only (127.0.0.1:9001); GraphQL is served at / and a health probe at /health
  • nginx terminating TLS on :443 (with :80 redirecting to HTTPS), serving the admin UI and reverse-proxying /graphql to the backend
  • A per-VM HTTP Basic Auth credential generated on first boot — Graphweaver ships no login wall of its own, so nginx is the security boundary and no default or shared credential ships in the image
  • graphweaver.service and nginx.service as systemd units, enabled and active
  • 24/7 cloudimg support

Graphweaver is distributed under the MIT licence.

Secure by default — a per-VM admin credential

Graphweaver's admin dashboard and GraphQL API are unauthenticated by default. This image makes security the default: the backend binds to the loopback interface only and is never exposed directly, and nginx enforces HTTP Basic Auth over TLS across both the admin dashboard and the API. No default or shared credential ships in the image — the build-time credential is removed at capture. On first boot a one-shot service resolves your public URL, regenerates a per-VM TLS certificate, generates a unique per-VM admin password (written to a root-only file), and only then creates the marker that lets nginx open port 443. There is never a window in which a fresh VM serves the dashboard or API without the per-VM credential.

The Graphweaver admin dashboard showing the seeded Project entity

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 comfortable starting point (the running app uses roughly 0.8 GiB); scale up for heavier workloads or larger datasets. NSG inbound: allow 22/tcp from your management network, and 80/tcp + 443/tcp from wherever you browse Graphweaver (:80 only redirects to :443).

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Graphweaver 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), HTTP (80) and HTTPS (443). Then Review + create -> Create.

Step 2 - Deploy from the Azure CLI

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

Step 3 - Connect to your VM

ssh azureuser@<vm-public-ip>

The message of the day shows your VM's Graphweaver dashboard URL.

Step 4 - Confirm the services are running

Graphweaver runs as two systemd units - the GraphQL backend and nginx:

systemctl is-active graphweaver.service nginx.service
active
active

The backend is bound to the loopback interface only; nginx is the only service on public ports (:80 and :443):

sudo ss -tln | grep -E ':(80|443|9001) '
LISTEN 0  511          0.0.0.0:443       0.0.0.0:*
LISTEN 0  511          0.0.0.0:80        0.0.0.0:*
LISTEN 0  511        127.0.0.1:9001      0.0.0.0:*

The backend health endpoint answers on loopback, the dashboard requires authentication, and plain HTTP redirects to HTTPS:

curl -s  -o /dev/null -w 'backend /health     -> HTTP %{http_code}\n' http://127.0.0.1:9001/health
curl -sk -o /dev/null -w 'dashboard (no auth) -> HTTP %{http_code}\n' https://127.0.0.1/
curl -s  -o /dev/null -w 'http :80 redirect   -> HTTP %{http_code}\n' http://127.0.0.1/
backend /health     -> HTTP 200
dashboard (no auth) -> HTTP 401
http :80 redirect   -> HTTP 301

Graphweaver services, loopback backend + nginx binding, and health on the VM

Step 5 - Read the per-VM admin credential

On first boot the VM writes a root-only file with your dashboard URL, the admin username and the unique password generated for this VM:

sudo grep -E '^GRAPHWEAVER_ADMIN_USER=|^GRAPHWEAVER_URL=' /root/graphweaver-credentials.txt
GRAPHWEAVER_ADMIN_USER=admin
GRAPHWEAVER_URL=https://<vm-public-ip>/

The GRAPHWEAVER_ADMIN_PASSWORD line in that file holds your unique password. Only the per-VM credential is accepted - anonymous access, a wrong password, and the common admin:admin default are all rejected with 401:

U=$(sudo grep '^GRAPHWEAVER_ADMIN_USER=' /root/graphweaver-credentials.txt | cut -d= -f2-)
P=$(sudo grep '^GRAPHWEAVER_ADMIN_PASSWORD=' /root/graphweaver-credentials.txt | cut -d= -f2-)
Q='{"query":"{ projects { id } }"}'
curl -sk -o /dev/null -w 'per-VM credential -> HTTP %{http_code}\n' -u "$U:$P" -H 'Content-Type: application/json' -X POST https://127.0.0.1/graphql --data "$Q"
curl -sk -o /dev/null -w 'no credential     -> HTTP %{http_code}\n' -H 'Content-Type: application/json' -X POST https://127.0.0.1/graphql --data "$Q"
curl -sk -o /dev/null -w 'default admin:admin-> HTTP %{http_code}\n' -u admin:admin -H 'Content-Type: application/json' -X POST https://127.0.0.1/graphql --data "$Q"
per-VM credential -> HTTP 200
no credential     -> HTTP 401
default admin:admin-> HTTP 401

Secure by default: the per-VM credentials file and a live auth round-trip

Step 6 - First login

Open Graphweaver in your browser (accept the self-signed certificate warning, or install a trusted certificate first - see below):

https://<vm-public-ip>/

When prompted for HTTP authentication, enter the username admin and the GRAPHWEAVER_ADMIN_PASSWORD from Step 5. The admin dashboard loads with your data sources and entities in the sidebar.

Exploring the admin dashboard

The dashboard lists your data source (mikro-orm-sqlite) and its entities (Project and Task). Selecting an entity shows a filterable data grid of its records, drawn live from the GraphQL API:

The Project entity grid rendered from the GraphQL API

Selecting a row opens a detail panel where you can view and edit the record; Save issues a GraphQL mutation back to the API:

Editing a Project record in the admin dashboard

The second seeded entity, Task, shows the same generated grid over its own table:

The Task entity grid

Every entity gets a generated detail/edit view automatically - no per-entity UI code:

Editing a Task record in the admin dashboard

Querying the GraphQL API

The same API that powers the dashboard is available directly. Send an authenticated GraphQL query to /graphql:

U=$(sudo grep '^GRAPHWEAVER_ADMIN_USER=' /root/graphweaver-credentials.txt | cut -d= -f2-)
P=$(sudo grep '^GRAPHWEAVER_ADMIN_PASSWORD=' /root/graphweaver-credentials.txt | cut -d= -f2-)
curl -sk -u "$U:$P" -H 'Content-Type: application/json' -X POST https://127.0.0.1/graphql \
  --data '{"query":"{ projects { id name status } }"}' | jq -c '.data.projects[]'
{"id":"1","name":"Website Redesign","status":"Active"}
{"id":"2","name":"Mobile App","status":"Active"}
{"id":"3","name":"Data Migration","status":"Planning"}
{"id":"4","name":"API Gateway","status":"Active"}

The tasks entity is queryable the same way, and Graphweaver auto-generates create, update and delete mutations for every entity:

U=$(sudo grep '^GRAPHWEAVER_ADMIN_USER=' /root/graphweaver-credentials.txt | cut -d= -f2-)
P=$(sudo grep '^GRAPHWEAVER_ADMIN_PASSWORD=' /root/graphweaver-credentials.txt | cut -d= -f2-)
curl -sk -u "$U:$P" -H 'Content-Type: application/json' -X POST https://127.0.0.1/graphql \
  --data '{"query":"{ tasks { id title assignee priority } }"}' | jq -c '.data.tasks[]'

Live GraphQL queries returning the seeded demo data

How the demo app is wired

The built application lives under /opt/graphweaver/app, and the SQLite datastore under /opt/graphweaver/data:

ls /opt/graphweaver/app/dist
sudo ls -la /opt/graphweaver/data
admin-ui  backend
...
database.sqlite

The demo defines two typed entities (Project and Task) in src/backend, each backed by a MikroBackendProvider over the SQLite connection. To model your own data, add entity + schema files under src/backend, then rebuild with pnpm run build (setting VITE_GRAPHWEAVER_API_URL=/graphql so the admin UI keeps calling the API through nginx) and restart graphweaver.service. Graphweaver's own documentation covers connecting additional data sources (PostgreSQL, MySQL, REST) and adding authentication.

Security updates

The image is captured fully patched (including Ubuntu phased updates) and unattended-upgrades stays enabled, so security patches keep flowing on your VM. There should be no held-back packages:

echo "held=[$(apt-mark showhold)]"
systemctl is-enabled unattended-upgrades.service
held=[]
enabled

The OS security baseline and runtime footprint

Your data

Graphweaver stores its SQLite database under /opt/graphweaver/data:

sudo du -sh /opt/graphweaver/data

Snapshot the VM's OS disk in Azure to back up your data, or copy /opt/graphweaver/data/database.sqlite to external storage on a schedule.

Enabling a trusted TLS certificate

The image ships a per-VM self-signed certificate so HTTPS works out of the box; browsers will warn until you install a trusted certificate. For production, point a DNS A record at the VM's public IP, ensure 443/tcp is open in the NSG, then install certbot and let it manage the nginx certificate. Replace the placeholders with your own domain and email:

sudo apt-get update
sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.example.com -m you@example.com --agree-tos

certbot configures the HTTPS server block and sets up automatic renewal, and Graphweaver is then available at your domain with a trusted certificate.

Upgrading Graphweaver

The demo pins the @exogee/graphweaver packages to a specific version. To upgrade, edit the versions in /opt/graphweaver/app/package.json, then run sudo -u graphweaver bash -c 'cd /opt/graphweaver/app && pnpm install && VITE_GRAPHWEAVER_API_URL=/graphql pnpm run build' and sudo systemctl restart graphweaver. Always snapshot the OS disk first. cloudimg support can assist with planning and performing upgrades.

Support

This image is backed by 24/7 cloudimg support covering deployment, upgrades, integrations, TLS termination and schema customisation. Contact us by email and chat.

Graphweaver is a trademark of its respective owner. All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.