Observability Azure

openGemini on Ubuntu 24.04 LTS on Azure

| Product: openGemini on Ubuntu 24.04 LTS by cloudimg

This image ships openGemini 1.4.1 on Ubuntu 24.04 LTS, configured and ready to accept authenticated writes and queries from the first boot of every deployed virtual machine.

openGemini is an open source distributed time series database purpose built for metrics, observability and IoT workloads. It ingests and queries high volumes of time stamped measurements over a simple HTTP API, stores them efficiently with columnar compression, and speaks a familiar InfluxQL style query language. It runs perfectly well as a single node, which is how this image ships, and scales out to a distributed cluster when you need one.

What makes this image different

Authentication is enforced, not optional. Out of the box, openGemini ships with HTTP authentication disabled: every write and query is permitted without credentials. This image never runs that way. The server is configured with auth-enabled = true, and a random administrator password unique to your virtual machine is generated on first boot. An unauthenticated query is refused with 401.

No credential is baked into the image. The entire openGemini data, metadata and write ahead log tree is destroyed before the image is captured, so no user, database or build time password can ride into your virtual machine. A first boot service creates a pristine store, generates the per VM administrator credential, creates the default cloudimg database, and writes the credential to a root only file. There is no default login anywhere in the image.

Internal ports stay private. Only the HTTP query and write API on port 8086 is reachable off the machine. The meta, store, RPC and internal service ports are all bound to 127.0.0.1, and the Marketplace plan opens port 22 only. Section 7 shows exactly how to reach the API safely and how to open it to your own virtual network when you need to.

1. Deploy the virtual machine

Deploy from the Azure Marketplace listing, or from the gallery image with the Azure CLI. The recommended size is Standard_B2s or larger.

az vm create \
  --resource-group my-resource-group \
  --name my-opengemini-vm \
  --image "openGemini on Ubuntu 24.04 LTS by cloudimg" \
  --size Standard_B2s \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard

2. Connect to the virtual machine

ssh azureuser@<vm-ip>

3. Confirm openGemini is running

systemctl status opengemini.service --no-pager

The service is a native systemd unit and starts automatically on boot. A companion first boot unit, opengemini-firstboot.service, is what generates the per VM administrator credential described above.

openGemini service status on a freshly booted virtual machine, showing the native systemd unit active and running

Confirm the version:

ts-server version 2>&1 | grep -a single
single: 1.4.1

The HTTP API also answers an unauthenticated liveness probe, which is convenient for a load balancer or a health check:

curl -sS -o /dev/null -w 'ping returns HTTP %{http_code}\n' http://localhost:8086/ping
ping returns HTTP 204

4. Retrieve your credential

First boot generates a random administrator password and writes it to a file readable only by root.

sudo cat /root/opengemini-credentials.txt

Expected output, with the password value unique to your virtual machine:

# openGemini — Per-VM Credentials (generated on first boot; unique to this VM).
# Stored in plain text ONLY here (0600 root:root). Keep it safe.
OPENGEMINI_USER=admin
OPENGEMINI_PASSWORD=<OPENGEMINI_PASSWORD>
OPENGEMINI_HTTP_ENDPOINT=http://<vm-ip>:8086
OPENGEMINI_DEFAULT_DATABASE=cloudimg

5. Run your first query

openGemini exposes an HTTP query API that speaks an InfluxQL style language and returns JSON. Every query must authenticate.

curl -sS -u 'admin:<OPENGEMINI_PASSWORD>' -G 'http://localhost:8086/query' \
  --data-urlencode 'q=SHOW DATABASES' | jq .
{
  "results": [
    {
      "statement_id": 0,
      "series": [
        {
          "name": "databases",
          "columns": ["name"],
          "values": [["cloudimg"]]
        }
      ]
    }
  ]
}

Confirm that an unauthenticated request is genuinely refused:

curl -sS -o /dev/null -w 'anonymous query returns HTTP %{http_code}\n' \
  -G 'http://localhost:8086/query' --data-urlencode 'q=SHOW DATABASES'
anonymous query returns HTTP 401

An authenticated openGemini query listing the default database over the HTTP API, and an unauthenticated request being refused with HTTP 401

6. Write and read time series data

Writes use the line protocol and go to the /write endpoint. A point is a measurement, optional tags, one or more fields and an optional timestamp in nanoseconds. Here we write a few weather readings into the default cloudimg database.

NOW=$(date +%s000000000)
curl -sS -o /dev/null -w 'write returns HTTP %{http_code}\n' \
  -u 'admin:<OPENGEMINI_PASSWORD>' \
  -XPOST 'http://localhost:8086/write?db=cloudimg' \
  --data-binary "weather,location=london temperature=17.4,humidity=71 ${NOW}"
write returns HTTP 204

Read the point back. Written points become queryable within a few seconds:

curl -sS -u 'admin:<OPENGEMINI_PASSWORD>' -G 'http://localhost:8086/query' \
  --data-urlencode 'db=cloudimg' \
  --data-urlencode 'q=SELECT * FROM weather' | jq .
{
  "results": [
    {
      "statement_id": 0,
      "series": [
        {
          "name": "weather",
          "columns": ["time", "humidity", "location", "temperature"],
          "values": [["2026-07-19T05:31:56Z", 71, "london", 17.4]]
        }
      ]
    }
  ]
}

openGemini supports aggregation, grouping and time bucketing. Write a small series and run a grouped aggregate over it:

NOW=$(date +%s000000000)
curl -sS -o /dev/null -w 'batch write HTTP %{http_code}\n' \
  -u 'admin:<OPENGEMINI_PASSWORD>' \
  -XPOST 'http://localhost:8086/write?db=cloudimg' \
  --data-binary "weather,location=paris temperature=19.1,humidity=64 ${NOW}
weather,location=berlin temperature=15.8,humidity=80 ${NOW}"
curl -sS -u 'admin:<OPENGEMINI_PASSWORD>' -G 'http://localhost:8086/query' \
  --data-urlencode 'db=cloudimg' \
  --data-urlencode 'q=SELECT MEAN(temperature) AS mean_temp, MAX(humidity) AS max_humidity FROM weather' | jq '.results[0].series'

Writing weather readings into openGemini with the line protocol and reading them back with an authenticated query over the HTTP API

7. Network posture, and opening openGemini to your virtual network

The HTTP API listens on all interfaces on port 8086, while every internal port is bound to loopback only:

ss -tln | grep -E ':(8086|8087|8088|8091|8092|8400|8401) '
LISTEN 0      4096         0.0.0.0:8086       0.0.0.0:*
LISTEN 0      4096       127.0.0.1:8087       0.0.0.0:*
LISTEN 0      4096       127.0.0.1:8088       0.0.0.0:*
LISTEN 0      4096       127.0.0.1:8091       0.0.0.0:*
LISTEN 0      4096       127.0.0.1:8092       0.0.0.0:*
LISTEN 0      4096       127.0.0.1:8400       0.0.0.0:*
LISTEN 0      4096       127.0.0.1:8401       0.0.0.0:*

Port 8086 is the query and write API and it is authenticated. The meta port 8091, the RPC port 8092, the store ports 8400 and 8401 and the flight port 8087 are all on 127.0.0.1 and are not reachable from outside the machine. The Marketplace plan opens port 22 only.

The openGemini listening ports, showing the authenticated HTTP API on 8086 and every internal port bound to loopback

Reaching openGemini from your workstation without opening anything

The simplest safe path is an SSH tunnel. Nothing is exposed to the network:

ssh -L 8086:localhost:8086 azureuser@<vm-ip>

Then point any client at http://localhost:8086 on your own machine.

Opening the API to your own virtual network

The HTTP API already listens on all interfaces, so to let another host in your virtual network reach it you only need to open the port in the network security group, to your virtual network's address range only. Never open a database port to 0.0.0.0/0.

az network nsg rule create --resource-group my-resource-group --nsg-name my-nsg \
  --name allow-opengemini-vnet --priority 1001 --access Allow --protocol Tcp \
  --destination-port-ranges 8086 --source-address-prefixes 10.0.0.0/16

Because authentication is already enforced, the API is authenticated from the moment you expose it. For traffic that crosses a network, enable HTTPS by setting https-enabled = true with a certificate and key in the [http] section of /etc/opengemini/openGemini.conf, then restart the service.

8. Managing users and databases

Create an additional database:

curl -sS -u 'admin:<OPENGEMINI_PASSWORD>' -G 'http://localhost:8086/query' \
  --data-urlencode 'q=CREATE DATABASE metrics' | jq .

Create a non administrator user and grant it read and write on a single database:

curl -sS -u 'admin:<OPENGEMINI_PASSWORD>' -G 'http://localhost:8086/query' \
  --data-urlencode "q=CREATE USER app WITH PASSWORD 'Str0ng!AppPass2026'" | jq .
curl -sS -u 'admin:<OPENGEMINI_PASSWORD>' -G 'http://localhost:8086/query' \
  --data-urlencode 'q=GRANT ALL ON metrics TO app' | jq .

openGemini enforces password complexity and rejects weak passwords, so choose a strong value. List the users to confirm:

curl -sS -u 'admin:<OPENGEMINI_PASSWORD>' -G 'http://localhost:8086/query' \
  --data-urlencode 'q=SHOW USERS' | jq .

9. Configuration and data locations

The single node configuration lives at /etc/opengemini/openGemini.conf. The data, metadata and write ahead log live under /var/lib/opengemini, and logs are written to /var/log/opengemini.

sudo systemctl show -p FragmentPath opengemini.service
ls -1 /var/lib/opengemini

After editing the configuration, restart the service:

sudo systemctl restart opengemini

10. Keeping openGemini patched

The operating system and every apt managed component on this image patch normally with apt-get update && apt-get upgrade, and unattended upgrades run exactly as they do on stock Ubuntu.

openGemini itself is not an apt package. This image installs the official upstream release binary, pinned to version 1.4.1 and verified against its published checksum before installation. To move to a newer openGemini release, download the official tarball for that version from the openGemini releases page, verify its checksum, install the ts-server binary over /usr/local/bin/ts-server, and restart the service. Alternatively, take the republished cloudimg image, which is rebuilt on a freshly patched base.

11. Licence

openGemini is licensed under the Apache License 2.0. The full licence text is on the image:

cat /usr/share/doc/cloudimg/opengemini-LICENSE

Support

This image is supported by cloudimg. If you hit a problem with the image, contact support@cloudimg.co.uk. For questions about openGemini itself, the upstream project documentation is at docs.opengemini.org.