InfluxDB: Time-Series Database for Metrics and IoT
Purpose-built database for metrics, events, and IoT data. Telegraf integration and Grafana dashboards.
Introduction
InfluxDB is a purpose-built time-series database designed to handle high write and query loads for timestamped data. Whether you’re collecting server metrics, IoT sensor readings, application performance data, or real-time analytics, InfluxDB provides the performance and features needed to store, query, and visualize time-series data efficiently.
For homelabbers, InfluxDB is the cornerstone of a comprehensive monitoring stack, working seamlessly with Telegraf for data collection and Grafana for visualization.
What You’ll Learn:
- Deploy InfluxDB 2.x with Docker and understand the architecture
- Install and configure Telegraf for automated metrics collection
- Write Flux queries to analyze time-series data
- Set up data retention policies and downsampling
- Integrate InfluxDB with Grafana for powerful visualizations
- Configure alerting and notifications
- Monitor InfluxDB itself for health and performance
- Collect IoT sensor data and Home Assistant metrics
Prerequisites:
- Docker and Docker Compose installed
- Basic understanding of time-series data concepts
- Command-line proficiency
- Homelab server with minimum 2GB RAM, 20GB storage
- Recommended: 4GB+ RAM for production monitoring workloads
Part 1: Understanding InfluxDB
What is InfluxDB?
InfluxDB is an open-source time-series database (TSDB) optimized for fast, high-availability storage and retrieval of time-series data. Unlike general-purpose databases, InfluxDB is specifically designed for data that includes timestamps—metrics, events, and analytics.
Key Characteristics:
- Purpose-Built for Time-Series: Optimized data structures for timestamped data
- High Write Throughput: Handles millions of data points per second
- Efficient Storage: Automatic compression and retention policies
- Powerful Query Language: Flux (InfluxDB 2.x) for complex time-series analysis
- Built-in UI: Web-based interface for queries, dashboards, and tasks
- Ecosystem Integration: Native Telegraf, Grafana, and third-party support
- Downsampling: Automatically aggregate old data for storage efficiency
Why InfluxDB for Homelabs?
Technical Advantages:
Optimized for Time-Series Workloads
- Write-optimized storage engine
- Timestamp-based indexing
- Automatic data retention and compaction
- Efficient time-range queries
Complete Monitoring Stack
- InfluxDB: Storage
- Telegraf: Data collection (100+ plugins)
- Flux: Query language
- Built-in visualization and alerts
Scalability
- Single-node for homelabs (millions of points/sec)
- Clustering for enterprise (optional)
- Efficient compression (10:1 typical)
Rich Feature Set
- Continuous queries (InfluxDB 1.x)
- Tasks (InfluxDB 2.x) for data transformation
- User-defined functions
- Anomaly detection
- Forecasting and predictions
Common Homelab Use Cases:
- System Monitoring: CPU, memory, disk, network metrics
- Container Metrics: Docker, Kubernetes resource usage
- Network Monitoring: SNMP, ping, bandwidth
- IoT Sensors: Temperature, humidity, power consumption
- Home Automation: Home Assistant state changes
- Application Metrics: Response times, error rates, throughput
- Energy Monitoring: Solar panels, smart plugs, power meters
- Weather Stations: Personal weather data collection
InfluxDB vs. Alternatives
| Feature | InfluxDB | Prometheus | TimescaleDB | Graphite |
|---|---|---|---|---|
| Type | Purpose TSDB | TSDB | PostgreSQL ext | TSDB |
| Write Speed | Excellent | Good | Good | Excellent |
| Query Language | Flux/InfluxQL | PromQL | SQL | Functions |
| Data Model | Tags/Fields | Labels/Values | Relational | Hierarchical |
| Retention | Built-in | Basic | Manual | Carbon rules |
| Downsampling | Continuous queries | Recording rules | Continuous agg | Aggregation |
| UI | Built-in | Basic | None | Graphite-web |
| Push/Pull | Push | Pull | Push | Push |
| Best For | General TSDB | Metrics | SQL users | Legacy apps |
InfluxDB 2.x Architecture
Data Model:
Bucket (like a database)
├── Measurement (like a table)
│ ├── Tags (indexed metadata)
│ │ ├── host=server1
│ │ ├── region=us-east
│ │ └── datacenter=dc1
│ ├── Fields (actual values)
│ │ ├── cpu_usage=45.2
│ │ ├── memory_used=2048
│ │ └── disk_free=500000
│ └── Timestamp
│ └── 2024-12-16T10:30:00Z Key Concepts:
- Bucket: Container for time-series data (replaces “database” in 1.x)
- Measurement: Collection of data points (like a table)
- Tags: Indexed key-value metadata for filtering
- Fields: Actual metric values (not indexed)
- Timestamp: When the data point was recorded
- Organization: Top-level container for buckets and users
InfluxDB 2.x Stack:
InfluxDB 2.x Server
├── Storage Engine (TSM - Time-Structured Merge Tree)
│ ├── WAL (Write-Ahead Log)
│ ├── Cache (in-memory)
│ └── TSM Files (compressed on disk)
├── Query Engine (Flux)
│ ├── Parser
│ ├── Optimizer
│ └── Executor
├── Tasks Engine
│ ├── Downsampling
│ ├── Alerting
│ └── Data transformation
└── HTTP API
├── /api/v2/write
├── /api/v2/query
└── UI endpoints Part 2: Installing InfluxDB with Docker
Quick Start Deployment
Create project directory:
mkdir -p ~/influxdb-homelab
cd ~/influxdb-homelab Create docker-compose.yml:
version: '3.8'
services:
influxdb:
image: influxdb:2.7-alpine
container_name: influxdb
hostname: influxdb
restart: unless-stopped
environment:
# Initial setup (only used on first run)
DOCKER_INFLUXDB_INIT_MODE: setup
DOCKER_INFLUXDB_INIT_USERNAME: admin
DOCKER_INFLUXDB_INIT_PASSWORD: ${INFLUXDB_PASSWORD:-ChangeMe123!}
DOCKER_INFLUXDB_INIT_ORG: homelab
DOCKER_INFLUXDB_INIT_BUCKET: metrics
DOCKER_INFLUXDB_INIT_RETENTION: 30d
DOCKER_INFLUXDB_INIT_ADMIN_TOKEN: ${INFLUXDB_TOKEN}
ports:
- "8086:8086"
volumes:
# Data persistence
- influxdb-data:/var/lib/influxdb2
# Configuration
- influxdb-config:/etc/influxdb2
networks:
- influxdb-network
healthcheck:
test: ["CMD", "influx", "ping"]
interval: 30s
timeout: 10s
retries: 5
start_period: 30s
# Resource limits
deploy:
resources:
limits:
cpus: '2'
memory: 4G
reservations:
cpus: '0.5'
memory: 512M
volumes:
influxdb-data:
driver: local
driver_opts:
type: none
o: bind
device: /mnt/storage/influxdb-data
influxdb-config:
driver: local
networks:
influxdb-network:
driver: bridge Create secure credentials (.env):
# Generate strong password and token
INFLUXDB_PASSWORD=$(openssl rand -base64 32)
INFLUXDB_TOKEN=$(openssl rand -base64 32)
# Save to .env
cat > .env <<EOF
INFLUXDB_PASSWORD=$INFLUXDB_PASSWORD
INFLUXDB_TOKEN=$INFLUXDB_TOKEN
EOF
chmod 600 .env
echo "InfluxDB admin password: $INFLUXDB_PASSWORD"
echo "InfluxDB admin token: $INFLUXDB_TOKEN"
echo "Save these credentials securely!" Deploy InfluxDB:
# Start InfluxDB
docker-compose up -d
# View logs
docker-compose logs -f influxdb
# Verify status
docker-compose ps
docker exec influxdb influx ping Access InfluxDB UI:
Navigate to http://your-server-ip:8086
Login with:
- Username:
admin - Password: Your generated password
Initial Configuration via UI
Create Additional Buckets:
- Click “Load Data” → “Buckets”
- Click “Create Bucket”
- Name:
iot_sensors - Retention:
90d - Click “Create”
Create API Tokens:
- Click “Load Data” → “API Tokens”
- Click “Generate API Token”
- Choose “Read/Write Token”
- Select buckets and permissions
- Copy token and save securely
Explore Data:
- Click “Data Explorer”
- Select bucket and measurement
- Build queries visually
Part 3: Telegraf for Data Collection
Installing Telegraf
Add to docker-compose.yml:
version: '3.8'
services:
influxdb:
# ... (previous influxdb config)
telegraf:
image: telegraf:1.29-alpine
container_name: telegraf
hostname: telegraf
restart: unless-stopped
environment:
# InfluxDB connection
INFLUX_URL: http://influxdb:8086
INFLUX_TOKEN: ${INFLUXDB_TOKEN}
INFLUX_ORG: homelab
INFLUX_BUCKET: metrics
volumes:
# Configuration
- ./telegraf.conf:/etc/telegraf/telegraf.conf:ro
# System access for metrics
- /var/run/docker.sock:/var/run/docker.sock:ro
- /sys:/host/sys:ro
- /proc:/host/proc:ro
- /etc:/host/etc:ro
networks:
- influxdb-network
depends_on:
influxdb:
condition: service_healthy
# Privileged mode for full system access
privileged: true
volumes:
influxdb-data:
driver: local
influxdb-config:
driver: local
networks:
influxdb-network:
driver: bridge Configuring Telegraf
Create telegraf.conf:
# Telegraf Configuration
# Global settings
[agent]
interval = "10s"
round_interval = true
metric_batch_size = 1000
metric_buffer_limit = 10000
collection_jitter = "0s"
flush_interval = "10s"
flush_jitter = "0s"
precision = "0s"
hostname = "homelab-server"
omit_hostname = false
###############################################################################
# OUTPUT PLUGINS #
###############################################################################
# InfluxDB v2 output plugin
[[outputs.influxdb_v2]]
urls = ["${INFLUX_URL}"]
token = "${INFLUX_TOKEN}"
organization = "${INFLUX_ORG}"
bucket = "${INFLUX_BUCKET}"
timeout = "5s"
###############################################################################
# INPUT PLUGINS #
###############################################################################
# System metrics
[[inputs.cpu]]
percpu = true
totalcpu = true
collect_cpu_time = false
report_active = false
[[inputs.disk]]
ignore_fs = ["tmpfs", "devtmpfs", "devfs", "iso9660", "overlay", "aufs", "squashfs"]
[[inputs.diskio]]
# devices = ["sda", "sdb"]
[[inputs.kernel]]
# no configuration
[[inputs.mem]]
# no configuration
[[inputs.processes]]
# no configuration
[[inputs.swap]]
# no configuration
[[inputs.system]]
# no configuration
[[inputs.net]]
# interfaces = ["eth0"]
[[inputs.netstat]]
# no configuration
# Docker metrics
[[inputs.docker]]
endpoint = "unix:///var/run/docker.sock"
gather_services = false
container_names = []
container_name_include = []
container_name_exclude = []
timeout = "5s"
perdevice = true
total = false
docker_label_include = []
docker_label_exclude = []
# Temperature sensors (if available)
[[inputs.sensors]]
remove_numbers = false
# SMART disk health
[[inputs.smart]]
path_smartctl = "/usr/sbin/smartctl"
# devices = ["/dev/sda", "/dev/sdb"]
# attributes = true
# excludes = []
# Ping connectivity checks
[[inputs.ping]]
urls = ["8.8.8.8", "1.1.1.1"]
count = 4
ping_interval = 1.0
timeout = 2.0
interface = ""
# HTTP response time
[[inputs.http_response]]
urls = [
"http://google.com",
"http://homelab.local:3000"
]
response_timeout = "5s"
method = "GET"
follow_redirects = true
# InfluxDB monitoring
[[inputs.influxdb]]
urls = ["http://influxdb:8086/metrics"]
###############################################################################
# ADDITIONAL USEFUL INPUTS #
###############################################################################
# SNMP (for network devices)
# [[inputs.snmp]]
# agents = ["192.168.1.1"]
# version = 2
# community = "public"
# [[inputs.snmp.field]]
# name = "hostname"
# oid = "RFC1213-MIB::sysName.0"
# MQTT (for IoT devices)
# [[inputs.mqtt_consumer]]
# servers = ["tcp://mosquitto:1883"]
# topics = ["homeassistant/#", "sensors/#"]
# data_format = "json"
# Nginx
# [[inputs.nginx]]
# urls = ["http://localhost/nginx_status"]
# PostgreSQL
# [[inputs.postgresql]]
# address = "host=postgres user=telegraf password=password dbname=postgres sslmode=disable"
# Redis
# [[inputs.redis]]
# servers = ["tcp://redis:6379"]
# password = "your_redis_password" Start Telegraf:
docker-compose up -d telegraf
docker-compose logs -f telegraf Verify data collection:
- Go to InfluxDB UI → Data Explorer
- Select
metricsbucket - You should see measurements like
cpu,mem,disk, etc.
Part 4: Flux Query Language
Flux Basics
Flux is InfluxDB 2.x’s functional query language.
Basic query structure:
from(bucket: "metrics")
|> range(start: -1h)
|> filter(fn: (r) => r._measurement == "cpu")
|> filter(fn: (r) => r._field == "usage_system")
|> aggregateWindow(every: 1m, fn: mean) Breaking it down:
from(bucket: "metrics")- Select data source|>- Pipe operator (passes data to next function)range(start: -1h)- Time window (last hour)filter()- Filter rowsaggregateWindow()- Downsample data
Common Flux Queries
1. CPU usage over time:
from(bucket: "metrics")
|> range(start: -24h)
|> filter(fn: (r) => r._measurement == "cpu")
|> filter(fn: (r) => r._field == "usage_user")
|> aggregateWindow(every: 5m, fn: mean, createEmpty: false)
|> yield(name: "mean") 2. Memory usage percentage:
from(bucket: "metrics")
|> range(start: -1h)
|> filter(fn: (r) => r._measurement == "mem")
|> filter(fn: (r) => r._field == "used_percent")
|> aggregateWindow(every: 1m, fn: last) 3. Disk free space:
from(bucket: "metrics")
|> range(start: -6h)
|> filter(fn: (r) => r._measurement == "disk")
|> filter(fn: (r) => r._field == "free")
|> filter(fn: (r) => r.path == "/")
|> aggregateWindow(every: 10m, fn: last)
|> map(fn: (r) => ({ r with _value: r._value / 1024.0 / 1024.0 / 1024.0 })) // Convert to GB 4. Network traffic rate:
from(bucket: "metrics")
|> range(start: -1h)
|> filter(fn: (r) => r._measurement == "net")
|> filter(fn: (r) => r._field == "bytes_recv" or r._field == "bytes_sent")
|> derivative(unit: 1s, nonNegative: true)
|> aggregateWindow(every: 1m, fn: mean) 5. Top 5 Docker containers by memory:
from(bucket: "metrics")
|> range(start: -5m)
|> filter(fn: (r) => r._measurement == "docker_container_mem")
|> filter(fn: (r) => r._field == "usage")
|> last()
|> group(columns: ["container_name"])
|> top(n: 5, columns: ["_value"]) 6. Calculate rate of change:
from(bucket: "metrics")
|> range(start: -1h)
|> filter(fn: (r) => r._measurement == "cpu")
|> filter(fn: (r) => r._field == "usage_system")
|> derivative(unit: 1s) 7. Alert if value exceeds threshold:
from(bucket: "metrics")
|> range(start: -5m)
|> filter(fn: (r) => r._measurement == "cpu")
|> filter(fn: (r) => r._field == "usage_user")
|> mean()
|> map(fn: (r) => ({
r with
_level:
if r._value >= 90.0 then "critical"
else if r._value >= 70.0 then "warning"
else "ok"
})) Variables in Flux
// Define variables
bucket_name = "metrics"
time_range = -24h
measurement_name = "cpu"
// Use in query
from(bucket: bucket_name)
|> range(start: time_range)
|> filter(fn: (r) => r._measurement == measurement_name) Part 5: Retention Policies and Downsampling
Understanding Data Retention
InfluxDB 2.x uses bucket retention periods to automatically delete old data.
Configure retention via UI:
- Load Data → Buckets
- Click on bucket name
- Edit retention period
- Options: Never (∞), or specific duration (7d, 30d, 90d, 1y)
Configure retention via CLI:
# Create bucket with 30-day retention
docker exec influxdb influx bucket create --name short_term --org homelab --retention 720h # 30 days
# Update existing bucket
docker exec influxdb influx bucket update --name metrics --retention 2160h # 90 days Creating Downsampling Tasks
Tasks run Flux queries on a schedule to downsample or transform data.
Example: Downsample hourly averages
option task = {
name: "downsample_hourly",
every: 1h,
offset: 5m
}
from(bucket: "metrics")
|> range(start: -1h)
|> filter(fn: (r) => r._measurement == "cpu")
|> aggregateWindow(every: 1h, fn: mean, createEmpty: false)
|> to(bucket: "metrics_hourly", org: "homelab") Create task via UI:
- Tasks → Create Task
- Paste Flux script
- Click “Save”
Retention strategy example:
Raw data (metrics bucket)
├── 10-second interval
├── 7-day retention
└── Downsampled to hourly → stored in metrics_hourly
Hourly aggregates (metrics_hourly bucket)
├── 1-hour interval
├── 90-day retention
└── Downsampled to daily → stored in metrics_daily
Daily aggregates (metrics_daily bucket)
├── 1-day interval
└── 2-year retention Part 6: Grafana Integration
Connecting InfluxDB to Grafana
Add InfluxDB as data source in Grafana:
- Configuration → Data Sources → Add data source
- Select “InfluxDB”
- Configure:
Query Language: Flux URL: http://influxdb:8086 Organization: homelab Token: your-influxdb-token Default Bucket: metrics - Click “Save & Test”
Creating Grafana Dashboards
Example panel: CPU Usage
- Create new dashboard → Add panel
- Data source: InfluxDB
- Query:
from(bucket: "metrics")
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|> filter(fn: (r) => r._measurement == "cpu")
|> filter(fn: (r) => r._field == "usage_user")
|> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false) - Visualization: Time series
- Panel title: “CPU Usage”
Example panel: Memory Usage
from(bucket: "metrics")
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|> filter(fn: (r) => r._measurement == "mem")
|> filter(fn: (r) => r._field == "used_percent")
|> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false) Import pre-built dashboards:
- Dashboard ID: 1443 (System Metrics)
- Dashboard ID: 13969 (Docker Monitoring)
- Dashboard ID: 928 (Telegraf System Dashboard)
Part 7: IoT and Home Assistant Integration
Collecting IoT Sensor Data
MQTT to InfluxDB via Telegraf:
Add to telegraf.conf:
[[inputs.mqtt_consumer]]
servers = ["tcp://mosquitto:1883"]
topics = [
"homeassistant/sensor/+/state",
"zigbee2mqtt/+",
"sensors/temperature/+"
]
data_format = "json"
json_string_fields = ["temperature", "humidity", "battery"]
tag_keys = ["device_name", "room"] Home Assistant Integration
Configure InfluxDB in Home Assistant:
Add to configuration.yaml:
influxdb:
host: influxdb
port: 8086
api_version: 2
ssl: false
token: !secret influxdb_token
organization: homelab
bucket: homeassistant
tags:
source: ha
tags_attributes:
- friendly_name
default_measurement: state
include:
entities:
- sensor.living_room_temperature
- sensor.bedroom_humidity
- sensor.power_consumption
- binary_sensor.front_door Query Home Assistant data:
from(bucket: "homeassistant")
|> range(start: -24h)
|> filter(fn: (r) => r.entity_id == "sensor.living_room_temperature")
|> filter(fn: (r) => r._field == "value")
|> aggregateWindow(every: 5m, fn: mean) Part 8: Backup and Monitoring
Backup InfluxDB
Backup all data:
# Create backup
docker exec influxdb influx backup /tmp/backup -t ${INFLUXDB_TOKEN}
# Copy backup from container
docker cp influxdb:/tmp/backup ./backup_$(date +%Y%m%d)
# Compress backup
tar -czf influxdb_backup_$(date +%Y%m%d).tar.gz ./backup_$(date +%Y%m%d) Automated backup script:
#!/bin/bash
BACKUP_DIR="/mnt/backups/influxdb"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
mkdir -p "$BACKUP_DIR"
docker exec influxdb influx backup /tmp/backup -t ${INFLUXDB_TOKEN}
docker cp influxdb:/tmp/backup "$BACKUP_DIR/backup_$TIMESTAMP"
tar -czf "$BACKUP_DIR/influxdb_$TIMESTAMP.tar.gz" "$BACKUP_DIR/backup_$TIMESTAMP"
rm -rf "$BACKUP_DIR/backup_$TIMESTAMP"
# Retention: keep last 7 days
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +7 -delete Restore from Backup
# Extract backup
tar -xzf influxdb_backup_20241216.tar.gz
# Copy to container
docker cp backup_20241216 influxdb:/tmp/
# Restore
docker exec influxdb influx restore /tmp/backup_20241216 -t ${INFLUXDB_TOKEN} Monitoring InfluxDB
Check InfluxDB metrics:
# Via HTTP API
curl http://localhost:8086/metrics
# Via Telegraf
# (Already configured in telegraf.conf under inputs.influxdb) Grafana dashboard for InfluxDB monitoring:
Import Dashboard ID: 12819 (InfluxDB 2.x Metrics)
Conclusion
You now have a comprehensive InfluxDB deployment optimized for time-series data collection and analysis in your homelab.
Key Takeaways:
- Purpose-Built: Optimized specifically for time-series data
- Complete Stack: InfluxDB + Telegraf + Grafana for full monitoring
- Powerful Queries: Flux language for complex time-series analysis
- Efficient Storage: Automatic compression and retention policies
- IoT Ready: Perfect for sensor data and Home Assistant integration
Next Steps:
- Configure additional Telegraf input plugins
- Create custom Grafana dashboards
- Set up alerting for critical metrics
- Implement downsampling tasks for long-term storage
- Explore ML/AI features for anomaly detection
Resources:
Happy time-series monitoring!
Guide Version: 1.0 Last Updated: December 2024 Target Audience: Homelab administrators, DevOps engineers, IoT enthusiasts Difficulty Level: Intermediate Estimated Time: 55 minutes