Op
Security Azure

OpenRelik on Ubuntu 24.04 on Azure User Guide

| Product: OpenRelik on Ubuntu 24.04 LTS on Azure

Overview

This guide covers the deployment and configuration of OpenRelik on Ubuntu 24.04 on Azure using cloudimg Azure Marketplace images. OpenRelik is an open source platform for collaborative digital forensics and incident response. Investigators create a folder for a case, upload the evidence they have collected, and run processing workflows over it from the browser. The processing runs on a pool of independent Celery workers, so a long job such as building a Plaso super timeline runs in the background while the team carries on working, and the results land back in the same case folder for everyone to review.

The cloudimg image ships the free and open source, Apache-2.0 licensed OpenRelik server, web UI, mediator, metrics exporter and four processing workers, run the officially supported way as the upstream containers pinned by image digest. All eleven containers are captured into the VM, so your instance starts without pulling several gigabytes. Because this platform holds evidence, nothing here ships with a known secret: the PostgreSQL password, the session secret, the JWT signing key and the administrator password are all generated for each VM on first boot, before the application is reachable, and Google single sign on ships deliberately unconfigured and closed rather than open. Backed by 24/7 cloudimg support.

OpenRelik is a trademark of its respective owner. This image is produced by cloudimg and is not affiliated with, endorsed by, or sponsored by OpenRelik or Google LLC. It ships the free and open source Apache-2.0 licensed software, unmodified.

The docker, openrelik-firstboot, openrelik, openrelik-postboot and nginx services all reporting active, and the eleven compose containers (server, UI, mediator, metrics, PostgreSQL, Valkey, Prometheus and the four Celery workers) all running

What is included:

  • OpenRelik server 0.7.0 (the Apache-2.0 licensed FastAPI backend), pinned by image digest
  • OpenRelik web UI 0.7.0 (the Apache-2.0 licensed Vue application), pinned by image digest
  • The OpenRelik mediator and Celery metrics exporter, pinned by image digest
  • Four processing workers: Plaso (super timelining), strings, grep and archive/disk-image extraction
  • PostgreSQL 17 for application data and Valkey 8 (BSD-3-Clause) as the Celery broker and result backend
  • Prometheus for task queue metrics
  • Docker Engine with the backend and UI published to the loopback interface only, fronted by nginx on port 80 at / (UI), /api/ (REST API) and /auth/ (local sign in)
  • openrelik.service, openrelik-firstboot.service, openrelik-postboot.service and nginx.service as systemd units, enabled and active on boot
  • A per instance PostgreSQL password, session secret, JWT signing key and administrator password generated per VM on first boot, never baked into the image
  • No default login, no shipped OAuth client secret, and an empty database on first boot
  • Ubuntu 24.04 LTS base with latest security patches applied at build time
  • Azure Linux Agent for seamless cloud integration and SSH key injection
  • 24/7 cloudimg support with guaranteed 24 hour response SLA

Prerequisites

  • Active Azure subscription, SSH public key, VNet + subnet in target region
  • Subscription to the OpenRelik listing on Azure Marketplace

Recommended virtual machine size: Standard_B2s (2 vCPU, 4 GB RAM) runs the whole stack and is the size this image is validated on. For real casework, and especially for Plaso super timelining over large disk images, use Standard_D4s_v5 or larger and attach a data disk for evidence. NSG inbound: allow 22/tcp from your management network and 80/tcp for the web UI from the networks your analysts use.

Step 1: Deploy from the Azure Portal

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for OpenRelik 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

RG="openrelik-prod"; LOCATION="eastus"; VM_NAME="openrelik-01"
GALLERY_IMAGE_ID="/subscriptions/<sub-id>/resourceGroups/azure-cloudimg/providers/Microsoft.Compute/galleries/cloudimgGallery/images/openrelik-ubuntu-24-04/versions/<version>"
SSH_KEY="$(cat ~/.ssh/id_rsa.pub)"
az group create --name "$RG" --location "$LOCATION"
az network vnet create -g "$RG" --name openrelik-vnet --address-prefix 10.100.0.0/16 --subnet-name openrelik-subnet --subnet-prefix 10.100.1.0/24
az network nsg create -g "$RG" --name openrelik-nsg
az network nsg rule create -g "$RG" --nsg-name openrelik-nsg --name allow-ssh --priority 100 \
  --source-address-prefixes "<your-mgmt-cidr>" --destination-port-ranges 22 --access Allow --protocol Tcp
az network nsg rule create -g "$RG" --nsg-name openrelik-nsg --name allow-http --priority 110 \
  --source-address-prefixes "<your-analyst-cidr>" --destination-port-ranges 80 --access Allow --protocol Tcp
az vm create -g "$RG" --name "$VM_NAME" --image "$GALLERY_IMAGE_ID" \
  --size Standard_B2s --storage-sku StandardSSD_LRS \
  --admin-username azureuser --ssh-key-values "$SSH_KEY" \
  --vnet-name openrelik-vnet --subnet openrelik-subnet --nsg openrelik-nsg --public-ip-sku Standard

Step 3: Connect to your VM

ssh azureuser@<vm-ip>

Step 4: Confirm the services are running

The platform runs as eleven containers under one openrelik.service, fronted by nginx. Confirm the services are active and list the containers:

sudo systemctl is-active docker openrelik nginx
sudo docker compose --env-file /opt/openrelik/config.env -f /opt/openrelik/docker-compose.yml ps

You will see the services report active and all eleven containers running. The backend (127.0.0.1:8710) and the web UI (127.0.0.1:8711) are bound only to the loopback interface; PostgreSQL, Valkey, Prometheus, the mediator, the metrics exporter and the four Celery workers publish no host port at all and are reachable only on the private container network. nginx on :80 is the single public front door.

Step 5: Verify the listener isolation

Because this platform holds evidence, it matters that only the intended ports face the network. List every listening TCP socket on the VM:

sudo ss -tln

Only 22 (SSH) and 80 (nginx) are bound to a routable address. Everything else is on 127.0.0.1 or on the private container bridge. This is asserted at build time by an automated check that first proves itself against a deliberate public bind before trusting its own verdict.

Every listening TCP socket on the VM, showing only 0.0.0.0:22 and 0.0.0.0:80 bound publicly with the backend and UI on 127.0.0.1, and the container port map showing PostgreSQL, Valkey, Prometheus, the mediator, the metrics exporter and the workers with no published host port

Step 6: Read the per instance credentials

A unique PostgreSQL password, session secret and JWT signing key were generated for this VM on the first boot, before any container started, and an administrator account was then seeded with a random password. Read them:

sudo cat /root/openrelik-credentials.txt

The file (mode 0600 root:root) holds ADMIN_USERNAME and ADMIN_PASSWORD (the account you sign in to the web UI with), plus WEB_URL and API_URL. None of these ship in the image; every value is unique to this VM, so no two instances share a credential and there is no default login to change.

Step 7: Verify the security model

The web UI loads without authentication, but every API endpoint that reads or writes case data requires a valid session. Confirm that an unauthenticated write is rejected, that a forged token is rejected, and that the per instance administrator credential authenticates the same call:

sudo /usr/local/sbin/openrelik-roundtrip.sh

The bundled prover reports OK after checking that a complete, well formed folder creation request is rejected with 401 when unauthenticated and again when sent with a forged signing key, that the byte identical request then succeeds with 201 using a real session from the per instance administrator, and that a wrong password and an empty password are both rejected. The positive control is the important half: it proves the rejections were authentication and not a malformed request.

The per instance credentials file at mode 0600 root root with the admin password redacted, and the bundled round trip prover reporting OK after rejecting unauthenticated and forged token writes with 401 and succeeding with 201 using a real session

Step 8: Prove a workflow really runs

Status codes do not prove a forensics platform works. The image ships an end to end prover that creates a real case folder, uploads a real evidence file containing a randomly generated marker, runs the real strings workflow on a real Celery worker, waits for it to finish, downloads the artefact the worker produced, and asserts the marker is inside it:

sudo /usr/local/sbin/openrelik-workflow-proof.sh

It reports WORKFLOW_OK with the folder, evidence, workflow and artefact identifiers, and tidies up the case it created.

The processing tasks registered on the Celery queue including Plaso Log2Timeline, Plaso Psort, Strings, Grep and the two extraction tasks, followed by the workflow prover reporting WORKFLOW_OK after a real strings worker processed the uploaded evidence and the artefact it produced contained the planted marker

Step 9: Open the web UI and sign in

Browse to http://<vm-ip>/ to reach OpenRelik. Sign in with the ADMIN_USERNAME and ADMIN_PASSWORD from Step 6. There is no self registration and no default account; additional users are created from the command line in Step 14.

The OpenRelik sign in page with the per instance admin username entered, the password masked, and the Login button

Step 10: Create a case folder

After signing in you land on the folder list, which is your case list. Choose New folder and name it for the incident you are working. Folders are the unit of collaboration in OpenRelik: evidence, workflows and results all live in a folder, and a folder can be shared with colleagues from the Share button.

The OpenRelik folder list showing a case folder named INC-2026-0142 Suspicious Host WKSTN-047 with its owner and last modified time, and a New folder button

Step 11: Upload evidence and run a workflow

Open the case folder and choose Upload files to add the artefacts you collected, then Create workflow, select the uploaded file, and add a task such as Strings, Grep, Extract files from archives or Plaso Log2Timeline. Run it and the task is dispatched to the matching Celery worker. Workflows are named Untitled workflow until you rename them.

The case folder INC-2026-0142 open, showing the uploaded evidence file wkstn047-memdump.bin at 1.4 kB alongside the workflow, with the Upload files, Create workflow and Share buttons

Step 12: Review the results

When the task completes it writes its output back into the case as a new file. Open it to read the artefact the worker produced directly in the browser, or use Download to pull it locally. Below, the strings worker has processed the collected artefact and produced a byte offset indexed listing in which the suspicious indicators, a staging URL, a persistence registry key, a command and control address and an encoded PowerShell invocation, are immediately readable.

The extracted output file wkstn047-memdump.bin.ASCII_strings open in the OpenRelik content viewer, showing byte offsets alongside recovered strings including a staging URL, a Run key persistence path, a command and control address and an encoded PowerShell command line

Step 13: Call the API from your own machine

Everything the UI does is backed by the REST API. Sign in to obtain a session cookie and a CSRF token, then call an endpoint:

COOKIES=$(mktemp)
ADMIN_USERNAME=$(sudo grep '^ADMIN_USERNAME=' /root/openrelik-credentials.txt | cut -d= -f2-)
ADMIN_PASSWORD=$(sudo grep '^ADMIN_PASSWORD=' /root/openrelik-credentials.txt | cut -d= -f2-)
curl -s -o /dev/null -c "$COOKIES" -X POST http://localhost/auth/local \
  --data-urlencode "username=$ADMIN_USERNAME" --data-urlencode "password=$ADMIN_PASSWORD"
CSRF=$(awk '/csrf_token/{print $7}' "$COOKIES" | tail -1)
curl -s -b "$COOKIES" -H "X-CSRF-Token: $CSRF" http://localhost/api/v1/folders/ | head -c 400
echo
curl -s -b "$COOKIES" -H "X-CSRF-Token: $CSRF" http://localhost/api/v1/taskqueue/tasks/registered | head -c 400
rm -f "$COOKIES"

The first call lists your case folders and the second lists every processing task registered on the queue. From your own workstation use http://<vm-ip>/ in place of http://localhost/.

Step 14: Manage user accounts

Accounts are managed with the server's admin.py utility. Add an analyst, or change a password:

cd /opt/openrelik
sudo docker compose --env-file config.env -f docker-compose.yml exec openrelik-server \
  python admin.py create-user analyst --password '<choose-a-strong-password>'

Add --admin to grant administrator rights. Change the seeded administrator password the same way with python admin.py change-password admin. Every new user automatically joins the built in Everyone group, and folder sharing is controlled per folder from the UI.

Step 15: Enable Google single sign on (optional)

This image ships with local authentication only, and Google single sign on deliberately disabled and closed: client_id and client_secret are empty, the allowlist is empty and public_access is false. cloudimg never ships an OAuth client secret. To enable it, create an OAuth client in your own Google Cloud project, then edit /opt/openrelik/config/settings.toml and set client_id, client_secret, and either workspace_domain or an explicit allowlist of permitted email addresses. Add google to OPENRELIK_AUTH_METHODS on the openrelik-ui service in /opt/openrelik/docker-compose.yml, then restart:

sudo systemctl restart openrelik

Leave public_access = false unless you genuinely intend anyone with a Google account to be able to sign in.

Step 16: Scale the worker pool

The image ships a worker concurrency tuned to fit a 2 vCPU appliance. On a larger VM, raise it: edit /opt/openrelik/docker-compose.yml and increase --concurrency on the worker services (openrelik-worker-strings, openrelik-worker-grep, openrelik-worker-plaso, openrelik-worker-extraction), then restart the stack with sudo systemctl restart openrelik. Plaso and extraction are the memory hungry workers; raise those last and watch memory before doing so.

Step 17: Server components

Component Version / Detail
Backend OpenRelik server 0.7.0 (FastAPI, pinned by image digest)
Web UI OpenRelik UI 0.7.0 (Vue, pinned by image digest)
Orchestration bridge OpenRelik mediator 0.7.0
Processing workers Plaso 0.5.0, strings 0.3.0, grep 0.2.0, extraction 0.5.0
Application database PostgreSQL 17 (created empty on first boot)
Task broker Valkey 8 (BSD-3-Clause), Celery broker and result backend
Metrics OpenRelik metrics exporter 0.7.0 with Prometheus v3
Front door nginx on :80 routing / to the UI, /api/ and /auth/ to the backend
Evidence store /opt/openrelik/data/artifacts
Per instance secrets DB password, session secret and JWT key generated first boot into /opt/openrelik/config.env and /opt/openrelik/config/settings.toml
Admin account per instance random password, seeded first boot into /root/openrelik-credentials.txt
Operating system Ubuntu 24.04 LTS (patched at build)
License Apache-2.0 (OpenRelik)

Step 18: Managing the service

sudo systemctl status openrelik --no-pager | head -12
sudo docker compose --env-file /opt/openrelik/config.env -f /opt/openrelik/docker-compose.yml logs --tail 40 openrelik-server

Restart the whole stack with sudo systemctl restart openrelik, follow a worker live with ... logs -f openrelik-worker-plaso, and view configuration in /opt/openrelik/config.env, /opt/openrelik/config/settings.toml and /opt/openrelik/docker-compose.yml. After changing configuration, restart the service to apply it.

Step 19: Use your own domain and HTTPS (production)

The image serves the UI and API over plain HTTP on port 80, which is convenient behind a load balancer or on a private network. Because this platform carries evidence and credentials, terminate TLS in front of it for any real deployment:

  • Front the VM with Azure Application Gateway, a load balancer with a managed certificate, or a CDN, and forward to nginx on port 80.
  • Or install your own certificate: add a TLS server block to /etc/nginx/sites-available/openrelik referencing your certificate and key, open 443/tcp on the NSG, then sudo systemctl reload nginx.
  • Point a DNS name you control at the VM public IP. The UI and backend read their public address at first boot from the resolved public IP, so use a stable public IP, or update OPENRELIK_SERVER_URL in /opt/openrelik/config.env and api_server_url / ui_server_url / allowed_origins in /opt/openrelik/config/settings.toml to your domain and restart.

Step 20: Security recommendations

  • Restrict the NSG. Allow TCP 80 only from your analysts' networks and TCP 22 only from your management network. Evidence should never be reachable from the open internet.
  • Terminate TLS in front of the app (Step 19) so credentials, evidence and results are encrypted in transit.
  • Rotate the seeded administrator password after first sign in, and create a named account per analyst (Step 14) so actions are attributable.
  • Keep single sign on closed unless configured deliberately, and never set public_access = true without an allowlist or workspace domain.
  • Keep the internal services private. PostgreSQL, Valkey, Prometheus and the workers publish no host port; keep it that way and never expose the container ports directly.
  • Put evidence on a dedicated encrypted disk for real casework, and back up /opt/openrelik/data alongside the PostgreSQL volume.
  • Keep the OS patched. Unattended security upgrades remain enabled on the running VM.

Step 21: Support and Licensing

OpenRelik and its workers are distributed under the Apache License 2.0. This cloudimg image bundles the unmodified official open source releases; cloudimg provides the packaging, the single nginx front door, the per instance secret and administrator generation, the listener isolation checks, the paired deploy guide, and 24/7 support with a guaranteed 24 hour response SLA. Valkey is used in place of Redis as the Celery broker so the image carries only permissively licensed components. OpenRelik is an independent open source project and this image is not affiliated with or endorsed by it.

Deploy on Azure

Launch OpenRelik on Ubuntu 24.04 LTS by cloudimg from the Azure Marketplace and follow this guide to a working digital forensics and incident response platform in minutes.