Install InfluxDB on VPS - Time Series Database
InfluxDB is a high-performance time series database designed to store massive amounts of timestamped data points — perfect for tracking CPU usage, memory consumption, disk I/O, sensor temperatures, stock prices, IoT metrics, and any data that changes over time with precise timestamps. Unlike relational databases (MySQL, PostgreSQL) that optimize for structured static data, InfluxDB specializes in fast writes and queries of metrics — it compresses data exceptionally well, using only 20-30% of the disk space compared to traditional SQL databases. This guide covers installing InfluxDB 2.x on your VPS, setting up Telegraf agent for automatic metric collection, and visualizing everything in Grafana.
Understanding Time Series Databases
A time series database stores data with associated timestamps — every metric value comes with a precise timestamp, enabling rapid queries and analysis over time. Key components include:
- Metrics: CPU usage = 45.2% at timestamp 14:30:00
- Tags: host=web1, region=us-east, env=production (indexed metadata for filtering)
- Fields: temperature=32.5, humidity=65 (numerical values you measure)
- Timestamp: 1719134400000 (milliseconds since epoch)
Traditional databases like Elasticsearch or SQL databases perform poorly with this use case — they're slow at time-based queries, aggregation, and analytics. InfluxDB was engineered specifically for reading and writing metrics efficiently while minimizing resource consumption.
Installing InfluxDB 2.x on VPS
# For Ubuntu/Debian
curl -fsSL https://repos.influxdata.com/influxdata-archive_compat.key | apt-key add -
echo "deb [signed-by=/usr/share/keyrings/influxdata-archive_compat.gpg] https://repos.influxdata.com/debian stable main" | tee /etc/apt/sources.list.d/influxdata.list
apt update && apt install -y influxdb2 influxdb2-cli
# For CentOS/RHEL
cat > /etc/yum.repos.d/influxdata.repo << 'EOF'
[influxdata]
name = InfluxData Repository
baseurl = https://repos.influxdata.com/rhel/\$releasever/\$basearch/stable
enabled = 1
gpgcheck = 1
gpgkey = https://repos.influxdata.com/influxdata-archive.key
EOF
yum install -y influxdb2
# Start and enable the service
systemctl start influxdb
systemctl enable influxdb
Creating Organizations and Buckets
InfluxDB uses the term "bucket" instead of "database" but serves the same purpose — a bucket is a storage space for time series data with its own namespace and retention settings.
# Set environment variables for CLI
export INFLUX_HOST=http://localhost:8086
export INFLUX_ORG=my-org
export INFLUX_BUCKET=metrics
# Initialize InfluxDB (web UI at http://localhost:8086)
influx setup \
--org my-org \
--bucket metrics \
--retention 30d \
--username admin \
--password MySecurePass123! \
--force
# Create an API token for Telegraf/Grafana
influx auth create \
--org my-org \
--description "Telegraf token" \
--read-bucket metrics \
--write-bucket metrics
Installing Telegraf Agent
Telegraf is a lightweight agent that runs on your VPS and automatically collects system metrics (CPU, memory, disk, network) then ships them to InfluxDB — eliminating the need to manually write data.
# Install Telegraf
apt install -y telegraf
# Create configuration
cat > /etc/telegraf/telegraf.conf << 'EOF'
[global_tags]
host = "vps-01"
environment = "production"
[agent]
interval = "10s"
round_interval = true
metric_batch_size = 1000
metric_buffer_limit = 10000
collection_jitter = "0s"
flush_interval = "10s"
flush_jitter = "0s"
precision = "ns"
logfile = ""
hostname = ""
omit_hostname = false
[[outputs.influxdb_v2]]
urls = ["http://localhost:8086"]
token = "YOUR_INFLUX_TOKEN"
organization = "my-org"
bucket = "metrics"
[[inputs.system]]
# CPU, memory, disk, network metrics
[[inputs.disk]]
ignore_fs = ["tmpfs", "devtmpfs"]
[[inputs.mem]]
[[inputs.net]]
[[inputs.cpu]]
collect_cpu_time = true
report_by_cpu = true
[[inputs.processes]]
[[inputs.docker]]
endpoint = "unix:///var/run/docker.sock"
container_names = []
timeout = "5s"
EOF
# Replace YOUR_INFLUX_TOKEN with the token from the previous step
# Start Telegraf
systemctl start telegraf
systemctl enable telegraf
# Check status
systemctl status telegraf
Setting Retention Policies and Downsampling
Retention policies control how long InfluxDB keeps your data — choosing appropriate retention dramatically reduces disk usage over time.
# Set retention policy for metrics bucket to 30 days
influx bucket update \
--org my-org \
--name metrics \
--retention 720h
# List all buckets
influx bucket list --org my-org
# Downsampling example using Flux: compress data older than 7 days to 1-hour intervals
# Use aggregateWindow() in your Flux queries:
# from(bucket:"metrics")
# |> range(start: -30d)
# |> aggregateWindow(every: 1h, fn: mean)
# |> to(bucket: "metrics-downsampled")
Connecting Grafana to InfluxDB
Grafana uses Flux query language to pull metric data from InfluxDB and create real-time dashboards visualizing your VPS health.
# Assuming Grafana runs at http://localhost:3000
# Log in, then navigate to: Home → Connections → Data sources → Add data source
# Select InfluxDB
# Query language: Flux
# URL: http://localhost:8086
# Organization: my-org
# Token: YOUR_INFLUX_TOKEN
# Bucket: metrics
# Save & test → should see "Successfully queried the InfluxDB API"
# Create a simple dashboard:
# Click + → Panel → Select InfluxDB data source
# Enter this Flux query:
# from(bucket: "metrics")
# |> range(start: -24h)
# |> filter(fn: (r) => r._measurement == "cpu")
# |> filter(fn: (r) => r._field == "usage_system")
# |> aggregateWindow(every: 1m, fn: mean)
Flux Query Language Basics
Flux is a functional query language designed for InfluxDB — similar to SQL but with more powerful data processing capabilities.
# Read metrics from the last 24 hours
from(bucket: "metrics")
|> range(start: -24h)
# Filter by measurement type
from(bucket: "metrics")
|> range(start: -24h)
|> filter(fn: (r) => r._measurement == "cpu")
# Filter by field
from(bucket: "metrics")
|> range(start: -24h)
|> filter(fn: (r) => r._measurement == "cpu")
|> filter(fn: (r) => r._field == "usage_system")
# Aggregate to 1-minute intervals
from(bucket: "metrics")
|> range(start: -24h)
|> filter(fn: (r) => r._measurement == "cpu")
|> aggregateWindow(every: 1m, fn: mean)
# Group by host
from(bucket: "metrics")
|> range(start: -24h)
|> filter(fn: (r) => r._measurement == "mem")
|> group(columns: ["host"])
|> aggregateWindow(every: 5m, fn: mean)
# Calculate 95th percentile of response times
from(bucket: "metrics")
|> range(start: -7d)
|> filter(fn: (r) => r._measurement == "http_request")
|> filter(fn: (r) => r._field == "response_time_ms")
|> quantile(q: 0.95)
Setting Up Alerts in InfluxDB
# Create a Notification Endpoint (Email, Slack, Webhook, etc.)
# In Web UI: Alerting → Notification Endpoints → Create
# Create an Alert Rule:
# Alerting → Alert Rules → Create
# Example Flux query for alert when CPU > 80% for 5 minutes:
# option task = {name: "High CPU Alert", every: 5m, offset: 0s}
# from(bucket: "metrics")
# |> range(start: -5m)
# |> filter(fn: (r) => r._measurement == "cpu")
# |> filter(fn: (r) => r._field == "usage_system")
# |> aggregateWindow(every: 1m, fn: mean)
# |> map(fn: (r) => ({r with _value: r._value / 100.0}))
# |> filter(fn: (r) => r._value > 0.8)
# |> group(columns: ["host"])
# Set threshold: If count() > 0 for 1 minute then Fire
# Then: Send notification to your configured endpoint
Verifying InfluxDB is Working Correctly
# Check InfluxDB API health
curl -s -i http://localhost:8086/health
# Enter InfluxDB shell
influx
# List all buckets
buckets
# Query recent metrics using Flux
from(bucket: "metrics") |> range(start: -1h) |> limit(n: 5)
# List all measurement names in metrics bucket
from(bucket: "metrics") |> range(start: -1h) |> group(columns: ["_measurement"]) |> distinct(column: "_measurement")
# Verify Telegraf is sending data
from(bucket: "metrics") |> range(start: -5m) |> filter(fn: (r) => r._measurement == "cpu")
# Exit the shell
exit
influx query from the command line to run Flux queries without entering interactive mode — for example: influx query 'from(bucket:"metrics") |> range(start: -24h) |> limit(n: 10)' --org my-orgTroubleshooting Common Issues
Error: "bucket not found" when querying
The bucket specified in Telegraf or Grafana configuration doesn't exist or has a different name.
# List available buckets
influx bucket list --org my-org
# If missing, create it
influx bucket create --org my-org --name metrics --retention 720h
# Verify bucket names match exactly in Telegraf and Grafana configs
Telegraf not sending data even though service is running
Token may have expired or configuration is incorrect — check Telegraf logs.
# View Telegraf logs
journalctl -u telegraf -n 50 -f
# If you see "401 Unauthorized", create a new token
influx auth create --org my-org --description "Telegraf" --read-bucket metrics --write-bucket metrics
# Copy the new token into /etc/telegraf/telegraf.conf and reload
systemctl reload telegraf
InfluxDB consuming excessive memory
InfluxDB caches data in memory — reduce cache limits or shorten retention period.
# In /etc/default/influxdb (Debian/Ubuntu):
INFLUXDB_HEAP_SIZE=2gb
# Restart InfluxDB
systemctl restart influxdb
# Check current memory usage:
free -h
systemctl status influxdb | grep Memory
Grafana shows no data despite InfluxDB having metrics
Bucket name in data source may be incorrect or time range doesn't match when data was collected.
# In Grafana: Configuration → Data sources → InfluxDB
# Verify "Bucket" value matches the actual bucket name
# Try selecting "Last 24 hours" instead of "Last 7 days"
# Use the Explore tab to test queries and time ranges directly
Flux queries are slow or timing out
Queries touching too much data need optimization — use aggregation and limiting.
# Use aggregateWindow() to reduce resolution
from(bucket: "metrics")
|> range(start: -30d)
|> filter(fn: (r) => r._measurement == "cpu")
|> aggregateWindow(every: 1h, fn: mean)
# Use limit() to reduce record count
from(bucket: "metrics")
|> range(start: -24h)
|> limit(n: 1000)
# Use sample() for statistical sampling
from(bucket: "metrics")
|> range(start: -7d)
|> sample(n: 100)
Frequently Asked Questions
How does InfluxDB differ from Prometheus?
Prometheus uses a pull model — the Prometheus server pulls metrics from exporters (like node_exporter). InfluxDB uses a push model — Telegraf or your application pushes metrics to InfluxDB. Prometheus excels at alerting and short-term metrics (default 15-day retention). InfluxDB excels at long-term storage and historical analysis thanks to superior compression. Both work great with Grafana for visualization.
Can InfluxDB do clustering and replication?
The open source InfluxDB doesn't include built-in clustering — clustering requires InfluxDB Enterprise (paid). For basic high availability on a single VPS, use regular backups with influx backup or set up dual writes where Telegraf sends data to both primary and secondary InfluxDB instances.
What data does InfluxDB accept (tags vs fields vs timestamps)?
InfluxDB requires: measurement (name), timestamp (time), fields (numeric values). Tags are optional but indexed metadata as strings — too many unique tag values (high cardinality) increases memory usage. Fields are numerical values meant for aggregation (mean, sum, max) and aren't indexed — using fields instead of tags reduces memory pressure. Design your schema carefully to avoid high cardinality tags.