InfluxDB 3 Core on Ubuntu 22.04 on Azure User Guide
Overview
This image runs InfluxDB 3 Core as a single node time series database on Ubuntu 22.04 LTS. InfluxDB 3 Core is the open source edition of InfluxData's ground up rewrite of the InfluxDB engine in Rust, built on Apache Arrow, DataFusion, and Parquet. It is a complete architectural replacement for the Go based InfluxDB 2.x and 1.x, not an incremental release. The storage layer is columnar and Parquet backed, queries run through DataFusion, and both SQL and InfluxQL are first class query languages on the same data. The binary is a single statically compiled Rust executable with no Java, no Python, and no other embedded runtime, which means the image has zero runtime CVE surface from bundled virtual machines or interpreters.
Authentication is enforced with bearer tokens on every HTTP call. On the very first boot of every deployed virtual machine, a unique admin token is generated, a default database named cloudimg is created, and the token is written to a single file readable only by root. Two virtual machines launched from the same gallery image never share credentials. There is no username and password pair to remember; a single opaque token authenticates writes, queries, and admin operations, and you create additional lower privileged tokens for applications.
The HTTP API listens on port 8181, not the classic InfluxDB 1.x or 2.x port 8086. Writes use the InfluxDB line protocol, queries use SQL or InfluxQL over HTTP, and there is no embedded dashboard UI the way InfluxDB 2.x shipped. Recommended visualisation is Grafana, which has a first class InfluxDB data source that speaks to the v3 HTTP API directly.
The image is intended for teams that want a production posture single node time series store on day one, without spending hours on packaging, systemd plumbing, token bootstrap, or database creation. It is not a replicated cluster, it is not TLS encrypted out of the box, and it does not ship with an embedded web UI. Section 17 covers TLS termination and the security posture you want before putting customer traffic through the server.
The brand is lowercase cloudimg throughout this guide. All cloudimg URLs in this guide use the form https://www.cloudimg.co.uk.
Prerequisites
Before you deploy this image you need:
- A Microsoft Azure subscription where you can create resource groups, virtual networks, and virtual machines
- Azure role permissions equivalent to Contributor on the target resource group
- An SSH public key for first login to the admin user account
- A virtual network and subnet in the same region as the Azure Compute Gallery the image is published into, with an associated network security group
- The Azure CLI (
azversion 2.50 or later) installed locally if you intend to use the CLI deployment path in Section 2 - The cloudimg InfluxDB 3 offer enabled on your tenant in Azure Marketplace
Step 1: Deploy the Virtual Machine from the Azure Portal
Navigate to Marketplace in the Azure Portal, search for InfluxDB 3, and select the cloudimg publisher entry. Click Create to begin the wizard.
On the Basics tab choose your subscription, target resource group, and region. The region must match the region your Azure Compute Gallery exposes the image in. Set the virtual machine name. Choose SSH public key as the authentication type, set the username to a name of your choice, and paste your SSH public key. Standard_D2s_v3 is the recommended starting size, because the Parquet columnar engine benefits from memory for query caching once real write throughput starts landing, and the 8 gigabyte RAM profile covers most single node observability workloads comfortably. Scale up to Standard_D4s_v3 or Standard_D8s_v3 for heavier write rates or retention windows that measure in weeks rather than days.
On the Disks tab the recommended OS disk type is Standard SSD. The InfluxDB 3 data directory lives at /var/lib/influxdb3. If you expect to ingest more than a few gigabytes per day, attach a separate Premium SSD data disk now and follow Section 16 after the server is running to move the data directory across.
On the Networking tab select your existing virtual network and subnet. Attach a network security group that allows inbound TCP 22 from your management IP range and inbound TCP 8181 only from the virtual network CIDR or the specific application server and Grafana subnets that need to talk to the server. Do not expose 8181 to the public internet. Bearer token authentication is strong, but transport is plain HTTP unless you terminate TLS in front of the server as described in Section 18, and an exposed time series database with a scraped token is an indefinite compromise.
On the Management, Monitoring, and Advanced tabs the defaults are appropriate. Click Review + create, wait for validation to pass, then click Create. Deployment takes around two minutes.
Step 2: Deploy the Virtual Machine from the Azure CLI
If you prefer the command line, use the gallery image resource identifier as the source. The exact resource identifier is published on your Partner Center plan. A representative invocation:
RG="influxdb-prod"
LOCATION="eastus"
VM_NAME="influxdb-01"
ADMIN_USER="influxops"
GALLERY_IMAGE_ID="/subscriptions/<sub-id>/resourceGroups/azure-cloudimg/providers/Microsoft.Compute/galleries/cloudimgGallery/images/influxdb-3-ubuntu-22-04/versions/<version>"
SSH_KEY="$(cat ~/.ssh/id_rsa.pub)"
az group create --name "$RG" --location "$LOCATION"
az network vnet create \
--resource-group "$RG" \
--name influxdb-vnet \
--address-prefix 10.40.0.0/16 \
--subnet-name influxdb-subnet \
--subnet-prefix 10.40.1.0/24
az network nsg create --resource-group "$RG" --name influxdb-nsg
az network nsg rule create \
--resource-group "$RG" --nsg-name influxdb-nsg \
--name allow-ssh-mgmt --priority 100 \
--source-address-prefixes "<your-mgmt-cidr>" \
--destination-port-ranges 22 --access Allow --protocol Tcp
az network nsg rule create \
--resource-group "$RG" --nsg-name influxdb-nsg \
--name allow-influxdb-vnet --priority 110 \
--source-address-prefixes 10.40.0.0/16 \
--destination-port-ranges 8181 --access Allow --protocol Tcp
az vm create \
--resource-group "$RG" \
--name "$VM_NAME" \
--image "$GALLERY_IMAGE_ID" \
--size Standard_D2s_v3 \
--storage-sku StandardSSD_LRS \
--admin-username "$ADMIN_USER" \
--ssh-key-values "$SSH_KEY" \
--vnet-name influxdb-vnet --subnet influxdb-subnet \
--nsg influxdb-nsg \
--public-ip-address "" \
--os-disk-size-gb 32
The --public-ip-address "" flag keeps the server off the public internet. Use a bastion host or your existing private connectivity to reach it.
Step 3: Connect via SSH
After deployment, find the private IP of the new virtual machine. From a host inside the same virtual network:
ssh influxops@<private-ip>
The first login may take a few seconds while cloud init finalises. Once you have a shell, the server has already been started by systemd and the first boot oneshot has already generated the per VM admin token and created the default database.
Step 4: Retrieve the Admin Bearer Token
The admin token is written by the influxdb-firstboot.service systemd oneshot the very first time the virtual machine boots. It lives in a single file, readable only by root:
sudo cat /stage/scripts/influxdb-credentials.log
You will see something like:
port=8181
default_database=cloudimg
token=apiv3_aB3dQ9pK1xVnE7sT3uYrL6cZw0jHm4f8x_g7TpLk2vR
sample_connect=curl -H "Authorization: Bearer apiv3_..." http://localhost:8181/health
Every customer virtual machine deployed from this image has a different token. The token is an opaque bearer credential, not a password pair. Treat it like a secret API key: paste it into your secrets manager, do not check it into version control, and rotate it before production as described in Section 14.
Step 5: Server Components
| Component | Version | Purpose |
|---|---|---|
| InfluxDB 3 Core | Pinned at build time (printed by influxdb3 --version) |
Rust time series engine: columnar Parquet storage, DataFusion query engine, HTTP API |
| Ubuntu | 22.04 LTS | Base operating system |
| systemd units | influxdb3.service, influxdb-firstboot.service | Process supervision and first boot token generation |
The influxdb3 binary is at /usr/bin/influxdb3, installed from the official InfluxData APT repository at repos.influxdata.com/debian stable main. Runtime configuration is passed as CLI flags expanded from the systemd EnvironmentFile at /etc/influxdb3/influxdb3.env; there is no traditional YAML or INI config file. The firstboot oneshot runs with Type=oneshot and RemainAfterExit=yes, gated by the sentinel file /var/lib/influxdb3/.firstboot-done, so it runs exactly once per virtual machine.
Step 6: Filesystem Layout
| Path | Owner | Purpose |
|---|---|---|
| /usr/bin/influxdb3 | root:root 0755 | InfluxDB 3 server and CLI (same binary, subcommands select mode) |
| /etc/influxdb3/influxdb3.env | root:root 0644 | systemd EnvironmentFile: node id, object store type, data dir, HTTP bind address |
| /etc/systemd/system/influxdb3.service | root:root 0644 | InfluxDB 3 server unit, expands the env file into the ExecStart flags |
| /etc/systemd/system/influxdb-firstboot.service | root:root 0644 | Oneshot that generates the admin token and creates the default database |
| /usr/local/sbin/influxdb-firstboot.sh | root:root 0750 | Firstboot script (invoked by the oneshot) |
| /usr/local/sbin/influxdb-start.sh, influxdb-stop.sh, setEnv.sh | root:root 0755 | Convenience wrappers around systemctl |
| /var/lib/influxdb3/ | influxdb:influxdb 0750 | Data directory: Parquet segments, write ahead log, object store metadata |
| /var/lib/influxdb3/.firstboot-done | influxdb:influxdb 0644 | Sentinel: presence means firstboot has already run |
| /stage/scripts/influxdb-credentials.log | root:root 0600 | Generated admin token, readable by root only |
InfluxDB 3 Core uses the local filesystem object store (--object-store file) with the data directory pointing at /var/lib/influxdb3. The server writes Parquet segments into subdirectories inside that tree, and compaction is automatic. Logs go to the systemd journal; view them with journalctl -u influxdb3 -f.
Step 7: Start, Stop, and Check Status
Use systemd directly:
sudo systemctl start influxdb3
sudo systemctl stop influxdb3
sudo systemctl restart influxdb3
sudo systemctl status influxdb3
Or the helper scripts:
sudo /usr/local/sbin/influxdb-start.sh
sudo /usr/local/sbin/influxdb-stop.sh
Tail the server logs via the journal:
sudo journalctl -u influxdb3 -f
The firstboot oneshot is separate. It runs exactly once on the customer's first boot and should show as active (exited) from then on:
sudo systemctl status influxdb-firstboot
Step 8: Verify the Server is Healthy
The HTTP /health endpoint is unauthenticated and returns 200 with a small JSON body when the server is ready:
curl http://localhost:8181/health
Expected output is similar to {"status":"ok"} or OK depending on version. A 200 response means the HTTP listener is bound, the query engine is initialised, and the object store is reachable.
Step 9: Write Time Series Data with the Line Protocol
InfluxDB 3 accepts writes in the InfluxDB line protocol. Writes do not use SQL INSERT; they use line protocol over HTTP. A single measurement point looks like:
measurement,tag_key=tag_value field_key=field_value timestamp_nanoseconds
POST one or more lines to /api/v3/write_lp?db=<database>:
TOKEN="$(sudo awk -F= '/^token=/ {print $2}' /stage/scripts/influxdb-credentials.log)"
curl -X POST "http://localhost:8181/api/v3/write_lp?db=cloudimg&precision=nanosecond" \
-H "Authorization: Bearer $TOKEN" \
--data-binary "temperature,location=office value=23.5"
You can batch many lines in a single request by putting one point per line in the body. Timestamps are optional; if you omit them, the server stamps the write at its current time. The precision query parameter accepts nanosecond, microsecond, millisecond, and second.
Common client libraries:
# Python with the influxdb3-python client
from influxdb_client_3 import InfluxDBClient3, Point
client = InfluxDBClient3(
host="http://<vm-ip>:8181",
token="<your-token>",
database="cloudimg",
)
point = Point("temperature").tag("location", "office").field("value", 23.5)
client.write(point)
// Node with axios
const axios = require("axios");
await axios.post(
"http://<vm-ip>:8181/api/v3/write_lp?db=cloudimg",
"temperature,location=office value=23.5",
{ headers: { Authorization: "Bearer <your-token>" } },
);
Step 10: Query with SQL
InfluxDB 3 speaks SQL natively. Use the HTTP endpoint /api/v3/query_sql:
curl -X POST "http://localhost:8181/api/v3/query_sql" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"db":"cloudimg","q":"SELECT * FROM temperature ORDER BY time DESC LIMIT 10"}'
Or use the CLI that ships with the binary:
sudo influxdb3 query \
--host http://localhost:8181 \
--token "$TOKEN" \
--database cloudimg \
"SELECT * FROM temperature ORDER BY time DESC LIMIT 10"
The response is a JSON array of rows by default. Use --format csv or --format pretty with the CLI for alternative output.
Step 11: Query with InfluxQL
For clients and dashboards that still speak InfluxQL (the v1.x query language), InfluxDB 3 exposes /api/v3/query_influxql. This is the compatibility path for existing Grafana dashboards and legacy tooling:
curl -X POST "http://localhost:8181/api/v3/query_influxql" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"db":"cloudimg","q":"SELECT mean(value) FROM temperature WHERE time > now() - 1h GROUP BY time(5m)"}'
New applications should prefer SQL; InfluxQL is there so you do not have to rewrite every dashboard on day one of a migration.
Step 12: Rotate the Admin Token
Bearer tokens do not expire on their own. Rotate the firstboot generated token before production, and then on whatever schedule your security policy requires. The rotation pattern is create a second admin token, switch your clients over, delete the first. Never delete the only admin token before the new one is known to work; the server has no superuser fallback.
# 1. Create a second admin token with a distinct name
sudo influxdb3 create token --admin --token "$TOKEN" --name "admin-rotated-$(date +%Y%m%d)" --format json
# Copy the token value from the output and update /stage/scripts/influxdb-credentials.log.
# 2. List current tokens so you can confirm the rotation and identify the old one
sudo influxdb3 show tokens --token "<new-admin-token>"
# 3. Delete the old token by its name (the firstboot default name is _admin)
sudo influxdb3 delete token --token-name "_admin" --token "<new-admin-token>"
You can also regenerate the existing _admin token in place (same name, new value) with sudo influxdb3 create token --admin --regenerate --format json and confirming at the prompt. In either case, every client that cached the old token needs its configuration updated.
Step 13: Additional Tokens for Applications
InfluxDB 3 Core exposes a single token type — admin. Scoped tokens with db:write or db:read permissions are an InfluxDB 3 Enterprise feature and are not available in Core. For a Core deployment you have three practical options for handling application access:
Option A: One admin token per application
Create a distinct admin token for each application with a descriptive name, and hand each application its own token. Every token has full server access, but you can rotate and revoke per application without touching any other client.
sudo influxdb3 create token --admin --token "$TOKEN" --name "grafana-prod" --format json
sudo influxdb3 create token --admin --token "$TOKEN" --name "app-writer-eu" --format json
sudo influxdb3 create token --admin --token "$TOKEN" --name "batch-ingest" --format json
When the Grafana host is decommissioned, sudo influxdb3 delete token --token-name "grafana-prod" --token "$TOKEN" revokes just that token.
Option B: Reverse proxy with per application credentials
Place nginx or Caddy in front of InfluxDB 3 on the same VM, terminate TLS there, and use the proxy's auth layer (basic auth, mTLS client certificates, or an OAuth2 introspection endpoint) to gate each application by its own credential. The proxy injects the single InfluxDB admin token on every forwarded request. This is the pattern that gives you real least privilege on Core.
Option C: Upgrade to Enterprise if scoped tokens are a hard requirement
InfluxDB 3 Enterprise supports scoped tokens natively through the same influxdb3 create token command with --permission flags. If your security model requires database or table level access control enforced by the database itself, plan a migration to Enterprise.
Rotate every application token on the same cadence as the admin token regardless of which option you choose.
Step 14: Reconfigure at Runtime with systemd Drop In Overrides
InfluxDB 3 has no traditional config file; runtime options are CLI flags expanded from /etc/influxdb3/influxdb3.env inside the systemd unit. To change a runtime option (bind address, data directory, node id, etc.) edit the env file:
sudo vi /etc/influxdb3/influxdb3.env
sudo systemctl restart influxdb3
To change anything systemd itself controls (user, ulimit, resource constraints, additional flags) use a drop in override rather than editing the shipped unit:
sudo systemctl edit influxdb3
An editor opens on an empty drop in file at /etc/systemd/system/influxdb3.service.d/override.conf. Add only the sections you want to change, for example:
[Service]
LimitNOFILE=131072
Environment="INFLUXDB3_LOG_LEVEL=debug"
Save and exit; systemd reloads and applies the override on the next restart. Drop in overrides survive package upgrades because they do not touch the base unit the APT package manages.
Step 15: Connect Grafana
Grafana's built in InfluxDB data source speaks to the InfluxDB 3 HTTP API directly. In Grafana:
- Add data source and pick InfluxDB.
- Query language: choose InfluxQL for compatibility with legacy dashboards, or SQL if your Grafana version supports the Flight SQL dialect against InfluxDB 3.
- URL:
http://<vm-private-ip>:8181. - Auth: toggle Custom HTTP Headers and add
Authorizationwith valueBearer <read-only-token>. Use the read only token from Section 13, not the admin token. - Database:
cloudimg(or whichever database the dashboard targets). - Click Save & Test; Grafana confirms the data source is reachable.
Now you can build panels. SELECT mean(value) FROM temperature WHERE $__timeFilter(time) GROUP BY time($__interval) is a good smoke test.
Step 16: Move Data to an Attached Premium Disk
For production workloads larger than the OS disk can comfortably hold, attach a Premium SSD data disk and move the data directory across.
# 1. Identify the new block device (look for the unpartitioned disk)
lsblk
# 2. Format and mount it
sudo mkfs.ext4 /dev/sdc
sudo mkdir -p /data
sudo mount /dev/sdc /data
sudo blkid /dev/sdc # copy the UUID into /etc/fstab for persistence
# 3. Stop InfluxDB and move the data directory
sudo systemctl stop influxdb3
sudo rsync -aAX /var/lib/influxdb3/ /data/influxdb3/
sudo chown -R influxdb:influxdb /data/influxdb3
sudo mv /var/lib/influxdb3 /var/lib/influxdb3.bak
# 4. Point the env file at the new location
sudo sed -i 's|INFLUXDB3_DATA_DIR=.*|INFLUXDB3_DATA_DIR=/data/influxdb3|' \
/etc/influxdb3/influxdb3.env
# 5. Restart and verify
sudo systemctl start influxdb3
sudo journalctl -u influxdb3 -f
Only after the server has started cleanly and your queries work should you delete /var/lib/influxdb3.bak.
Step 17: Troubleshooting
Cannot connect on 8181 from another host
Verify the server is bound to 0.0.0.0 rather than 127.0.0.1: sudo ss -tlnp | grep 8181. If only 127.0.0.1 is shown, check that the systemd env file has INFLUXDB3_HTTP_BIND_ADDR=0.0.0.0:8181 and restart. If the server is bound correctly, the problem is your Azure NSG; confirm inbound TCP 8181 is allowed from the caller's CIDR.
Write returns 401 or 403
The bearer token is missing, malformed, or has been deleted. Re read /stage/scripts/influxdb-credentials.log to confirm the current token, and be sure the Authorization: Bearer <token> header is present on every write. Tokens are long opaque strings; copying only part of one is a common mistake.
Write returns 404 for a database
The target database has not been created on this instance. The firstboot oneshot creates cloudimg as the default; other databases must be created explicitly:
sudo influxdb3 create database <name> --host http://localhost:8181 --token "$TOKEN"
Query returns zero rows even though writes succeeded
Two usual causes. The first is a time range filter that does not cover when the data was written, which is especially common if you relied on a time field in the line protocol rather than the server's clock. The second is that the write ahead log has not yet flushed to Parquet; writes are durable in the WAL immediately but queries read from Parquet on disk, and there is a short flush interval. Waiting a few seconds and retrying usually resolves the second case.
Disk usage climbs faster than expected
Compaction is automatic but not instantaneous. Check /var/lib/influxdb3/ size over time and compare against your ingest rate. If the directory grows much faster than ingest rate alone would explain, inspect journalctl -u influxdb3 for compaction errors. For very high cardinality workloads, consider increasing the disk size before trying to tune compaction settings.
InfluxDB 3 refuses to start after an env file change
Run sudo systemctl status influxdb3 and look at the last journal lines. A common cause is a typo in the env file that makes the expanded CLI flag invalid; fix the file and systemctl restart influxdb3.
Step 18: Security Recommendations
Never run this server without tokens. The bootstrap token is generated at firstboot and authentication is enforced from that moment; rotating the admin token before production is recommended but the token guard is already active out of the box.
Restrict port 8181 in the NSG to your application subnets and Grafana hosts. The public internet has no business reaching an observability database.
Terminate TLS in front of the server by installing nginx or Caddy on the same VM listening on 443, forwarding to 127.0.0.1:8181, and letting Certbot or Caddy's automatic TLS keep a valid certificate in place. The InfluxDB 3 HTTP listener is plain HTTP; do not expose it directly to anything outside the VM over a network you do not trust.
Use per application tokens with least privilege permissions. An application that only writes one database never needs an admin or read token. A Grafana user never needs write.
Rotate tokens periodically. There is no automatic rotation; put it on your security calendar.
Keep the system patched. The APT sources stay configured; sudo apt-get update && sudo apt-get upgrade regularly to pick up InfluxData and Ubuntu security updates.
Step 19: Support and Licensing
cloudimg provides 24/7/365 expert technical support for this image. Guaranteed response within 24 hours; one hour average for critical issues. Contact support@cloudimg.co.uk.
InfluxDB 3 Core is licensed under the MIT and Apache 2.0 licences by InfluxData. This image is a repackaged upstream distribution provided by cloudimg; additional charges apply for the pre configured image, ongoing maintenance, and the 24/7 support contract.
Visit www.cloudimg.co.uk/guides/influxdb-3-on-ubuntu-22-04-azure for the published version of this guide.
InfluxDB is a registered trademark of InfluxData, Inc. This image is a repackaged upstream distribution provided by cloudimg. Additional charges apply for build, maintenance, and 24/7 support.