Deployment guide

OpenObserve

Overview

OpenObserve is an open source, high-performance observability platform that brings your logs, metrics and traces together in one place, with a rich, built-in web interface. It ships as a single, self-contained Go binary that stores data on local disk. A single node runs the full search, dashboard and alerting experience with no external object store, and uses roughly a tenth of the storage footprint of Elasticsearch.

This SecureAnyCloud image installs the pinned OpenObserve 0.91.1 binary and runs it as the openobserve systemd service. OpenObserve is bound to loopback at 127.0.0.1:5080, so it is never exposed directly, and an nginx reverse proxy on port 80 sits in front of it. OpenObserve has native user accounts. A root user is created on the first boot of every VM, and all ingest and REST APIs use HTTP Basic Auth with those per-VM credentials. Anonymous telemetry is disabled by default, so the VM observes your data privately out of the box.

The local store (ingested logs, metrics and traces, plus the metadata database) lives on a dedicated Azure data disk mounted at /var/lib/openobserve.

What you get:

  • OpenObserve 0.91.1 installed as a single Go binary and running as the openobserve systemd service
  • Logs, metrics and traces with a built-in web UI on :80, fronted by nginx with OpenObserve bound to loopback only
  • A native per-VM root account, with a unique password generated on first boot; all APIs use HTTP Basic Auth
  • OpenObserve bound to 127.0.0.1:5080, so the application is never exposed to the network directly
  • Anonymous telemetry disabled by default for a private, self-hosted setup
  • A dedicated Azure data disk at /var/lib/openobserve that holds the local store and metadata database
  • An nginx proxy that forwards the WebSocket upgrade OpenObserve uses for live tail
  • openobserve.service and nginx.service as enabled, active systemd units
  • An unauthenticated /healthz endpoint for Azure Load Balancer health probes
  • 24/7 SecureAnyCloud support

Prerequisites

You need an active Azure subscription, an SSH key pair, and a VNet with a subnet in the target region.

Standard_B2s (2 vCPU / 4 GiB RAM) is a comfortable starting size for evaluation and light workloads. Scale up the VM and the data disk as your ingest volume grows.

Configure the network security group (NSG) to allow inbound 22/tcp from your management network, 80/tcp for the web UI and ingest, and 443/tcp if you add TLS. OpenObserve serves plain HTTP on port 80. For production, terminate TLS in front of it with your own domain and restrict access to trusted IP ranges (see Maintenance).

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for OpenObserve by SecureAnyCloud, and select Create.

On the Basics tab, 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).

Review the dedicated data disk on the Disks tab, then select Review + create and Create.

Step 2 - Deploy from the Azure CLI

# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:openobserve-ubuntu-24-04:default:latest
az vm create \
  --resource-group <your-rg> \
  --name openobserve \
  --image sac1647283583153:openobserve-ubuntu-24-04:default:latest \
  --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 openobserve --port 80 --priority 1010

Step 3 - Connect to your VM

ssh azureuser@<vm-public-ip>

Step 4 - Confirm the services are running

systemctl is-active openobserve.service nginx.service

Both services report active. OpenObserve stores and serves logs, metrics and traces on the loopback address 127.0.0.1:5080, and nginx fronts it on port 80. The local store lives on the dedicated Azure data disk mounted at /var/lib/openobserve.

Step 5 - Retrieve your root login

OpenObserve has native user accounts. First boot creates a root user and writes its email and unique password to a root-only file. Read the file with sudo:

sudo cat /root/openobserve-credentials.txt

The file contains OPENOBSERVE_USERNAME (the root email, admin@openobserve.local), OPENOBSERVE_PASSWORD and the OPENOBSERVE_URL to open in a browser. OpenObserve reads the password only at first start, from a separate 0640 env file (/etc/openobserve/root-user.env), so no plaintext password ships in the image. Store the password somewhere safe.

Step 6 - Confirm the health endpoint

nginx proxies an unauthenticated health endpoint for load balancers and probes. Request it from the VM:

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

The endpoint returns 200. It never requires authentication, so you can use it for an Azure Load Balancer health probe.

Step 7 - Confirm authentication and the streams API

The root user is set on first boot, so an unauthenticated API request returns HTTP 401. Nobody reaches your data without credentials. The following commands read the per-VM password from the credentials file and test four cases: an unauthenticated request is rejected, a wrong password is rejected, the correct password authenticates, and an authenticated call to the streams API returns JSON:

PW=$(sudo grep '^OPENOBSERVE_PASSWORD=' /root/openobserve-credentials.txt | cut -d= -f2-) E=admin@openobserve.local echo "unauth : $(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1/api/default/streams)" echo "wrongpw : $(curl -s -o /dev/null -w '%{http_code}' -u $E:wrong-pw http://127.0.0.1/api/default/streams)" echo "authed : $(curl -s -o /dev/null -w '%{http_code}' -u $E:$PW http://127.0.0.1/api/default/streams)" echo "streams : $(curl -s -u $E:$PW http://127.0.0.1/api/default/streams | python3 -c 'import sys,json;print(len(json.load(sys.stdin).get("list",[])),"stream(s)")')"

The output shows unauth : 401, wrongpw : 401, authed : 200 and then the stream count. Every API and the whole UI are reachable only with the per-VM credentials, because OpenObserve itself is bound to loopback and nginx is the only way in.

Step 8 - Sign in to the web UI

Browse to http://<vm-public-ip>/. On the sign-in page, enter the root email admin@openobserve.local and the password from Step 5, then select Login.

OpenObserve opens on its home view, with Logs, Metrics, Traces, Dashboards, Alerts and Streams in the left menu.

Step 9 - Search your logs

Open Logs from the left menu, pick a stream (for example app_logs) and a time range, then select Run query.

OpenObserve shows an interactive histogram of matching events over time, a searchable field list on the left (level, service, status, duration and more), and the raw log records below. Expand any record to see its full JSON. Type a query in the search bar to filter by field or full text, and drag on the histogram to zoom into a time window.

Step 10 - Ship your own data

OpenObserve ingests data over a simple HTTP API and through OpenTelemetry (OTLP), Fluent Bit, Vector, Filebeat, Logstash and more. The Data sources page under Data has ready-made snippets for each. The quickest test is to send a single log line over the JSON ingest API with the per-VM credentials:

PW=$(sudo grep '^OPENOBSERVE_PASSWORD=' /root/openobserve-credentials.txt | cut -d= -f2-) E=admin@openobserve.local curl -s -o /dev/null -w 'ingest -> %{http_code}\n' -u $E:$PW \
  -H 'Content-Type: application/json' \
  -d '[{"level":"info","service":"my-app","message":"hello from my application"}]' \
  http://127.0.0.1/api/default/my_app_logs/_json

The command prints ingest -> 200, and a new my_app_logs stream appears in Logs immediately. Point your applications, OpenTelemetry collectors or log shippers at this host on port 80 to search everything from one place.

Step 11 - Manage your streams

Open Streams under Data. Each stream (a named collection of logs, metrics or traces) is listed with its type, event count and on-disk size. You can filter the list by Logs, Metrics, Traces or Metadata. From here you configure retention, user-defined schemas and field settings for each stream.

Step 12 - Confirm the store lives on the dedicated disk

OpenObserve keeps its local store (the write-ahead log, the compacted parquet data files and the metadata database) under /var/lib/openobserve on the dedicated Azure data disk. Your observability history survives OS changes, and you can resize the disk independently. Confirm the mount:

findmnt /var/lib/openobserve

The mount is backed by a separate Azure data disk that is captured into the image and re-provisioned on every VM. The store grows under /var/lib/openobserve as you ingest data.

Maintenance

  • Password and users: The root password is set on first boot and read only at first start from /etc/openobserve/root-user.env. Once you are signed in as root, create additional users and rotate credentials from IAM / Users in the web UI.
  • Restrict access: OpenObserve serves plain HTTP on port 80. For production, restrict the UI to trusted IP ranges in your Network Security Group, and front it with TLS (for example certbot with your own domain) terminating on :443.
  • Loopback binding: OpenObserve is bound to 127.0.0.1:5080 through ZO_HTTP_ADDR / ZO_HTTP_PORT in /etc/openobserve/openobserve.env, so nginx is the only path in. Do not change the bind address to a public interface.
  • Scale out: A single node stores everything on local disk. For larger deployments, point OpenObserve at object storage (S3 or Azure Blob) and an external metadata database, and run it in cluster mode. See the OpenObserve documentation.
  • Ingest: Send data over the HTTP JSON API, OpenTelemetry (OTLP), Fluent Bit, Vector, Filebeat, Logstash and more. The Data sources page in the UI has copy-and-paste snippets for each.
  • Storage: All OpenObserve state lives under /var/lib/openobserve on the data disk. Back up that volume to protect your observability history, and resize the disk as ingest grows.
  • Telemetry: Anonymous telemetry is disabled by default through ZO_TELEMETRY=false in /etc/openobserve/openobserve.env, for a fully self-hosted, private setup.
  • Licensing (AGPL-3.0): OpenObserve is licensed under the GNU Affero General Public License v3.0, and the image ships the unmodified upstream binary. Under the AGPL, if you modify OpenObserve and offer the modified version to users over a network, you must also offer them the corresponding source of your modifications. Running the unmodified binary carries no such obligation.
  • Security patches: unattended-upgrades remains enabled, so the OS continues to receive security updates automatically.

Support

SecureAnyCloud provides 24/7 expert support for this image. Contact sales@secureanycloud.com.

Deploy on Azure

Launch OpenObserve Observability on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure