Use case · Time-series database

InfluxDB self hosted, 3 Core on a dedicated NVMe server

To run InfluxDB self hosted in 2026, install InfluxDB 3 Core, the current open-source edition (3.12.2 in InfluxData's apt repository on 31 October 2026), from the signed DEB package, which runs it under a sandboxed systemd unit, and set the admin token before the port is reachable. Core writes Parquet files to local disk, so its own NVMe drive suits it.

Configure the server

Which InfluxDB to install

InfluxDB 3 Core is InfluxData's current open-source line; Enterprise is the commercial build on the same engine. The README puts Core under MIT or Apache 2, at the user's choosing. Our general reading, not legal advice, is that both are permissive, so there is no duty to publish source; redistributed copies carry the copyright notice and licence text.

Core uploads usage telemetry hourly (CPU, memory, write and query counts, file counts and more; the docs say no database contents or queries), and disable-telemetry-upload stops it. InfluxData announced that the Docker latest tag points to Core from 15 September 2026, so pin version tags.

What Core does not do

LimitDefault in CoreConsequence
Databases5 per serverSplit data by table
Parquet files per query (query-file-limit)432At most about 72 hours of data, sometimes less, with 10-minute gen1 files; raising it costs memory and speed
Retention periodSet at create database onlyA change means a new database and a data move
NodesOneHigh availability, read replicas and long-range compaction are Enterprise
TokensAdmin tokens, the only kind its token docs coverEach token has every permission; give each client its own named one

Sizing the machine

InfluxData publishes no minimum hardware for Core; its performance-tuning guide gives example configurations, quoted below. The last column is our mapping onto the NVMe dedicated server lines, whole HPE Moonshot cartridges, one NVMe SSD or two in software RAID 1, 1 Gbps unmetered.

InfluxData examplenum-io-threadsexec-mem-pool-sizeOur line
4 cores, 16 GB RAM210GBXeon E3-1585L v5, 4 cores, 32 to 64 GB
16 cores, 64 GB RAM645GBXeon D-1500 with the 16-core D-1587, 64 GB or more
64 cores, 256 GB RAM8200GBBeyond the cartridges; see the full range

Both settings go in the TOML file (num-io-threads=6, exec-mem-pool-size="45gb") followed by a restart; the package's influxdb3-launcher script maps num-io-threads to its environment variable. Disk is retention times write rate, on drives from 240 GB to 3.84 TB. Take the RAID 1 pair; a mirror covers a dead drive, never a dropped database.

The E3-1585L v5 line is the m710x cartridge, which has an out-of-band console with virtual media, as does the m510; other cartridges have power control only. Ready servers go live about 30 minutes once payment is approved; configured builds take 4 to 24 hours. The lines run in five cities on our own network, AS19624.

Install it on Ubuntu 24.04

Until the first admin token exists, /api/v3/configure/token/admin accepts unauthenticated requests and Core listens on 0.0.0.0:8181; the setup guide warns that whoever claims that token can run code on the host. Its production fix is a preconfigured token, used below, with Core on loopback. Set up the firewall first. The OpenSSH profile opens port 22 only, so if sshd listens on another port, put that port (for example 2222/tcp) in place of OpenSSH before you run sudo apt-get update && sudo apt-get install -y ufw && sudo sed -i 's/^IPV6=.*/IPV6=yes/' /etc/default/ufw && sudo ufw allow OpenSSH && sudo ufw --force enable.

cd /tmp && curl -sLO https://repos.influxdata.com/influxdata-archive.key \
&& gpg --show-keys --with-fingerprint --with-colons ./influxdata-archive.key 2>&1 \
| grep -q '^fpr::*24C975CBA61A024EE1B631787C3D57159FC2F927:$' \
&& gpg --dearmor < influxdata-archive.key | sudo tee /usr/share/keyrings/influxdata-archive.gpg >/dev/null \
&& echo 'deb [signed-by=/usr/share/keyrings/influxdata-archive.gpg] https://repos.influxdata.com/debian stable main' \
| sudo tee /etc/apt/sources.list.d/influxdata.list \
&& sudo apt-get update && sudo apt-get install -y influxdb3-core \
|| echo "STOP - key check or apt install did not finish"
C=/etc/influxdb3/influxdb3-core.conf; T=/etc/influxdb3/admin-token.json
sudo test -f "$C" && sudo test ! -e "$T" && ! sudo grep -q '^http-bind' "$C" \
&& sudo influxdb3 create token --admin --offline --output-file "$T" \
&& sudo chown influxdb3:influxdb3 "$T" && sudo chmod 750 /etc/influxdb3 \
&& printf '%s\n' 'http-bind="127.0.0.1:8181"' "admin-token-file=\"$T\"" 'disable-telemetry-upload=true' \
| sudo tee -a "$C" >/dev/null && sudo systemctl enable --now influxdb3-core \
&& timeout 60 sh -c 'until curl -so /dev/null http://127.0.0.1:8181/health; do sleep 2; done' \
&& export INFLUXDB3_AUTH_TOKEN="$(sudo python3 -c 'import json,sys;print(json.load(open(sys.argv[1]))["token"])' "$T")" \
&& influxdb3 show databases && ss -ltn | grep -q '127.0.0.1:8181 ' && echo "ok - up on 127.0.0.1:8181" \
|| echo "STOP - read the recovery note under this block"

The first chain is the guide's DEB procedure, joined into one chain with -y, cd /tmp, < for the key and a STOP line added. The second chain is ours. Without --name, create token --admin --offline writes an operator token named _admin, no expiry, to a file it creates at mode 600 (influxdb3/src/commands/create/token.rs). We hand it to the influxdb3 user at 600, as the token guide asks, set /etc/influxdb3 to 750, and append three keys to the package's TOML file. The token export lasts for this shell; later, run export INFLUXDB3_AUTH_TOKEN="$(sudo python3 -c 'import json,sys;print(json.load(open(sys.argv[1]))["token"])' /etc/influxdb3/admin-token.json)".

Recovery after a STOP, by where it stopped.

  • In the first chain (key check or apt), start over by pasting the whole block.
  • Later on, run sudo test -d /var/lib/influxdb3/data/primary-node && echo started || echo never. If it prints started, Core has stored the token, so keep admin-token.json and read sudo journalctl -u influxdb3-core -n 50.
  • If it prints never, sudo tail -n 3 /etc/influxdb3/influxdb3-core.conf shows whether the three lines went in. Remove only those with sudo sed -i -e '/^http-bind="127.0.0.1:8181"$/d' -e '/^admin-token-file=/d' -e '/^disable-telemetry-upload=true$/d' /etc/influxdb3/influxdb3-core.conf, delete the token with sudo rm -f /etc/influxdb3/admin-token.json, and rerun the second chain.

Writing into it with Telegraf

The influxdb_v3 output needs Telegraf 1.38 or later; the same repository carried 1.40.2 on 31 October 2026. Run these in the shell that holds the token.

  1. sudo apt-get install -y telegraf
  2. influxdb3 create database --retention-period 30d telegraf, choosing the period now.
  3. influxdb3 create token --admin --name telegraf prints a token once; read -rs TT and paste it, keeping it out of shell history.
  4. `case "$TT" in apiv3_*) ! sudo grep -q '^INFLUX_TOKEN=' /etc/default/telegraf 2>/dev/null && sudo touch /etc/default/telegraf && sudo chmod 600 /etc/default/telegraf && printf 'INFLUX_TOKEN=%s\n' "$TT" | sudo tee -a /etc/default/telegraf >/dev/null && echo ok || echo "STOP - a token line is already there, or the write did not finish";; *) echo "STOP - TT is empty or not an apiv3_ token";; esac writes it once; the packaged telegraf.service` reads that file as environment.
  5. printf '[[outputs.influxdb_v3]]\n urls = ["http://127.0.0.1:8181"]\n token = "${INFLUX_TOKEN}"\n database = "telegraf"\n' | sudo tee /etc/telegraf/telegraf.d/influxdb3.conf, then sudo systemctl restart telegraf.
  6. influxdb3 query --database telegraf "SHOW TABLES" once metrics arrive.

Agents on other hosts need TLS and a public bind. Copy the certificate and key into /etc/influxdb3, owner root, group influxdb3, mode 640, then add both keys once with sudo grep -q '^tls-cert=' /etc/influxdb3/influxdb3-core.conf || printf '%s\n' 'tls-cert="/etc/influxdb3/cert.pem"' 'tls-key="/etc/influxdb3/key.pem"' | sudo tee -a /etc/influxdb3/influxdb3-core.conf >/dev/null (a duplicate key breaks the file), and change the bind line in place, because a second http-bind line makes the launcher's TOML parser reject the file; edit it in place using sudo sed -i 's/^http-bind=.*/http-bind="0.0.0.0:8181"/' /etc/influxdb3/influxdb3-core.conf. Restart Core. After each certificate renewal, copy the new files in the same way and restart Core again, and make sure the name points at this server. ufw still filters the port, so open it to the senders alone, e.g. sudo ufw allow from 203.0.113.10 to any port 8181 proto tcp. Local clients then need https and the certificate's name, so set urls = ["https://influx.example.com:8181"] in the Telegraf output and export INFLUXDB3_HOST_URL=https://influx.example.com:8181 for the CLI. MQTT devices go through a Mosquitto broker.

Backups that restore

Core has no backup command, and the docs warn that copies taken while it runs may be inconsistent. Our script stops Core for the copy (writes are refused meanwhile), skips table-snapshots, which regenerate on restart, adds /etc/influxdb3 (the token file makes the archive a secret) and /var/lib/influxdb3/plugins when it exists, verifies, and only then prunes archives older than 14 days, our choice. Telegraf's token in /etc/default/telegraf is not in the archive; after a move, create a new collector token.

# /usr/local/sbin/influxdb3-backup.sh, run by root with bash
umask 077
D=/var/lib/influxdb3/data; N=primary-node; B=/var/backups/influxdb3
A="$B/influxdb3-$(date +%F-%H%M%S).tar.gz"; X=
install -d -m 700 "$B" && test -d "$D/$N" || { echo "STOP - $D/$N not found"; exit 1; }
test -d /var/lib/influxdb3/plugins && X="-C /var/lib/influxdb3 plugins"
trap 'systemctl start influxdb3-core' EXIT
systemctl stop influxdb3-core \
&& tar -czf "$A.part" --exclude="$N/table-snapshots" -C "$D" "$N" -C / etc/influxdb3 $X \
&& systemctl start influxdb3-core && L=$(tar -tzf "$A.part") \
&& grep -q "^$N/catalog" <<<"$L" && grep -qx 'etc/influxdb3/admin-token.json' <<<"$L" \
&& mv "$A.part" "$A" && echo "ok $A" \
|| { rm -f "$A.part"; echo "STOP - no new archive was kept, read the lines above"; exit 1; }
find "$B" \( -name 'influxdb3-*.tar.gz' -o -name 'run-*.log' \) -mtime +14 -delete \
|| echo "prune did not finish; the new archive $A was kept"

Save it as /usr/local/sbin/influxdb3-backup.sh, run sudo install -d -m 700 /var/backups/influxdb3, test with sudo bash /usr/local/sbin/influxdb3-backup.sh until it prints ok, then schedule it with printf '%s\n' '20 3 * * * root bash /usr/local/sbin/influxdb3-backup.sh > /var/backups/influxdb3/run-$(date +\%F).log 2>&1' | sudo tee /etc/cron.d/influxdb3-backup. Pull the archives to another host with rsync -a, never --delete.

To restore, set A to the archive. Every check runs before anything is stopped, and the live folder is set aside, not deleted.

D=/var/lib/influxdb3/data; N=primary-node; P="$D/$N.previous"
A=/var/backups/influxdb3/influxdb3-YYYY-MM-DD-HHMMSS.tar.gz
sudo test -f "$A" && L=$(sudo tar -tzf "$A") && grep -q "^$N/catalog" <<<"$L" \
&& sudo test ! -e "$P" && sudo test -d "$D/$N" \
&& sudo systemctl stop influxdb3-core && sudo mv "$D/$N" "$P" \
&& sudo tar -C "$D" -xzf "$A" "$N" && sudo chown -R influxdb3:influxdb3 "$D/$N" \
&& sudo systemctl start influxdb3-core && sleep 15 && systemctl is-active --quiet influxdb3-core \
&& echo "ok - restored; the data from before sits in $P" \
|| echo "STOP - archive missing or unreadable or without a catalog, a leftover $P, no live folder, Core would not stop, an extract error, or files back but Core did not start (sudo journalctl -u influxdb3-core -n 50); if $P exists, roll back as below"

To roll back, run `D=/var/lib/influxdb3/data; N=primary-node; sudo test -d "$D/$N.previous" && sudo test ! -e "$D/$N.failed" && sudo systemctl stop influxdb3-core && { sudo test ! -e "$D/$N" || sudo mv "$D/$N" "$D/$N.failed"; } && sudo mv "$D/$N.previous" "$D/$N" && sudo systemctl start influxdb3-core && sleep 15 && systemctl is-active --quiet influxdb3-core && echo "ok - rolled back" || echo "STOP - no .previous folder, a .failed folder in the way, or Core did not start (read the journal)". Once satisfied, run sudo rm -rf "$D/$N.previous" "$D/$N.failed"` in the same shell.

A new machine takes six steps, in this order.

  1. The firewall command above, then only the first chain of the install block, down to its first STOP line. Skip the second chain, since the archive brings the token.
  2. sudo install -d -m 700 /var/backups/influxdb3, copy the archive in, then put its path in A.
  3. `D=/var/lib/influxdb3/data; N=primary-node; sudo tar -C / -xzf "$A" etc/influxdb3 && sudo systemctl enable --now influxdb3-core && timeout 60 sh -c "until sudo test -d $D/$N; do sleep 2; done" && echo "ok - ready to restore" || echo "STOP - extract or first start did not finish, read sudo journalctl -u influxdb3-core -n 50"`
  4. `sudo tar -tzf "$A" | grep -q '^plugins/' && { sudo tar -C /var/lib/influxdb3 -xzf "$A" plugins && sudo chown -R influxdb3:influxdb3 /var/lib/influxdb3/plugins && echo "ok - plugins restored" || echo "STOP - plugins extract did not finish"; } || echo "no plugins in this archive"`
  5. The restore block, with A set to the same archive.
  6. In the same shell, run export INFLUXDB3_AUTH_TOKEN="$(sudo python3 -c 'import json,sys;print(json.load(open(sys.argv[1]))["token"])' /etc/influxdb3/admin-token.json)", then revoke the old Telegraf token the restored catalog still holds with influxdb3 delete token --token-name telegraf -y (-y skips the prompt, per influxdb3/src/commands/delete.rs), then create a new one as in the Telegraf steps.

Upgrades only go forward

3.10 rewrote the catalog in a format 3.9 cannot read, and 3.11 refuses a catalog 3.12 has used; per the upgrade guide, only a catalog backup takes you back.

  1. sudo bash /usr/local/sbin/influxdb3-backup.sh and wait for ok.
  2. Read the release notes for what apt-cache policy influxdb3-core offers.
  3. sudo apt-get update && sudo apt-get install --only-upgrade influxdb3-core; the package's post-install restarts a running unit.
  4. influxdb3 --version and influxdb3 show databases.

Going back means sudo systemctl stop influxdb3-core first, because the package's post-install would otherwise restart it against the newer catalog, then sudo apt-get install --allow-downgrades influxdb3-core=VERSION with a version from that list, then the restore block with the pre-upgrade archive. Anything written after that archive is lost when you go back.

When this is the wrong setup

  • Months of raw data at speed, a standby node, or more than five databases point to Enterprise.
  • Pull-based scraping with alert rules fits the Prometheus and Grafana stack better.
  • Tens of terabytes outgrow one or two NVMe drives; rack servers take many.

Questions

Can a database's retention change later?

Not in Core. The period is set only at create database; a different one means a new database and a data move.

May a company run InfluxDB 3 Core without paying?

The README licenses its open-source code under MIT or Apache 2, your choice. Our general reading, not legal advice, is that both allow commercial use and redistribution with notices kept; Apache 2.0 adds a contributor patent licence that ends for anyone who files a patent suit claiming the work infringes. Enterprise is licensed separately.

Is Docker a better fit than the DEB package?

The install guide recommends the DEB for non-Docker production for its sandbox. In Docker, publish 127.0.0.1:8181:8181, as the setup guide shows, not 8181:8181, which listens on every address and is not filtered by ufw. Pin a tag such as 3.12-core rather than latest.

Put InfluxDB on its own cartridge

Pick the NVMe line, one drive or a RAID 1 pair, and run the blocks above on Ubuntu.

Configure the server

Related on Server Room

Other use cases