ELK Stack — Filebeat
What Is Filebeat?
Filebeat is a lightweight log shipper that monitors log files or locations you specify, collects log events, and forwards them to Elasticsearch or Logstash for indexing. It is the most widely deployed Beat and serves as the primary tool for log collection in the Elastic Stack.
Filebeat is designed to be reliable and low-latency. It uses a registry to track the read position of each file, ensuring that no log line is lost — even if the output (Elasticsearch or Logstash) is temporarily unavailable.
Filebeat Architecture
┌──────────────────────────────────────────────────────────┐
│ Filebeat │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Inputs │ │
│ │ │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ /var/log/ │ │ /app/logs/ │ │ container │ │ │
│ │ │ syslog │ │ app.log │ │ stdout │ │ │
│ │ └──────┬───────┘ └──────┬──────┘ └──────┬──────┘ │ │
│ │ │ │ │ │ │
│ └─────────┼─────────────────┼─────────────────┼────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Harvesters (one per file) │ │
│ │ Read each file line by line, track offset │ │
│ └──────────────────────┬──────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Spooler │ │
│ │ Aggregates events into batches │ │
│ └──────────────────────┬──────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Processors (optional) │ │
│ │ Enrich, filter, transform before shipping │ │
│ └──────────────────────┬──────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Output │ │
│ │ Elasticsearch │ Logstash │ Kafka │ File │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Registry (data/registry/filebeat/log.json) │ │
│ │ Tracks file offsets for at-least-once delivery │ │
│ └─────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────┘
Key Components
| Component | Description |
|---|---|
| Input | Defines the source of log data (file paths, container logs, stdin) |
| Harvester | One harvester per file — reads content line by line and sends to the spooler |
| Spooler | Aggregates events and batches them before sending to the output |
| Registry | Persists the last read offset for each file — survives restarts |
| Output | Destination for collected events (Elasticsearch, Logstash, Kafka, etc.) |
Installation
# Debian/Ubuntu
curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-8.17.0-amd64.deb
sudo dpkg -i filebeat-8.17.0-amd64.deb
# RHEL/CentOS
curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-8.17.0-x86_64.rpm
sudo rpm -vi filebeat-8.17.0-x86_64.rpm
# macOS (Homebrew)
brew install elastic/tap/filebeat-full
# Docker
docker pull docker.elastic.co/beats/filebeat:8.17.0
Complete filebeat.yml Configuration
Below is a comprehensive filebeat.yml that covers the most common settings:
# =========================== Filebeat Inputs ============================
filebeat.inputs:
# --- Log input: collect application logs ---
- type: log
id: app-logs
enabled: true
paths:
- /var/log/myapp/*.log
- /opt/app/logs/application.log
# Exclude lines that match a pattern
exclude_lines: ['^DEBUG']
# Include only lines that match a pattern
include_lines: ['^ERR', '^WARN', '^INFO']
# Exclude files matching a pattern
exclude_files: ['\.gz$']
# Add custom fields to every event from this input
fields:
app: myapp
environment: production
fields_under_root: true
# Tags for filtering in Logstash/ES
tags: ["app-logs", "production"]
# --- Multiline settings ---
multiline.type: pattern
multiline.pattern: '^\d{4}-\d{2}-\d{2}'
multiline.negate: true
multiline.match: after
multiline.max_lines: 50
multiline.timeout: 5s
# --- Container input: collect Docker/K8s container logs ---
- type: container
id: docker-logs
enabled: true
paths:
- /var/lib/docker/containers/*/*.log
# Parse container log format (docker-json, cri)
stream: all # stdout, stderr, or all
format: docker
fields:
source: docker
fields_under_root: true
# --- Stdin input (useful for testing/piping) ---
- type: stdin
id: stdin-input
enabled: false
# =========================== Filebeat Modules ============================
filebeat.config.modules:
path: ${path.config}/modules.d/*.yml
reload.enabled: true
reload.period: 10s
# ============================== Processors ===============================
processors:
- add_host_metadata:
when.not.contains.tags: forwarded
- add_cloud_metadata: ~
- add_docker_metadata: ~
- drop_event:
when:
regexp:
message: "^\\s*$"
# ========================= Elasticsearch Output ==========================
output.elasticsearch:
hosts: ["https://es-node-1:9200", "https://es-node-2:9200"]
protocol: "https"
username: "filebeat_writer"
password: "changeme"
index: "filebeat-%{[agent.version]}-%{+yyyy.MM.dd}"
ssl:
enabled: true
certificate_authorities: ["/etc/filebeat/certs/ca.crt"]
certificate: "/etc/filebeat/certs/filebeat.crt"
key: "/etc/filebeat/certs/filebeat.key"
# Bulk indexing settings
bulk_max_size: 2048
compression_level: 3
# ========================== Logstash Output ==============================
# output.logstash:
# hosts: ["logstash-host:5044"]
# ssl:
# certificate_authorities: ["/etc/filebeat/certs/ca.crt"]
# certificate: "/etc/filebeat/certs/filebeat.crt"
# key: "/etc/filebeat/certs/filebeat.key"
# loadbalance: true
# bulk_max_size: 2048
# ============================ Kafka Output ===============================
# output.kafka:
# hosts: ["kafka-1:9092", "kafka-2:9092", "kafka-3:9092"]
# topic: "filebeat-logs"
# partition.round_robin:
# reachable_only: true
# required_acks: 1
# compression: gzip
# max_message_bytes: 1000000
# ============================== Kibana ===================================
setup.kibana:
host: "https://kibana-host:5601"
ssl:
enabled: true
certificate_authorities: ["/etc/filebeat/certs/ca.crt"]
# ============================= Dashboards ================================
setup.dashboards.enabled: true
# ========================== ILM (Index Lifecycle) ========================
setup.ilm.enabled: true
setup.ilm.rollover_alias: "filebeat"
setup.ilm.pattern: "{now/d}-000001"
setup.ilm.policy_name: "filebeat"
# ============================== Logging ==================================
logging.level: info
logging.to_files: true
logging.files:
path: /var/log/filebeat
name: filebeat
keepfiles: 7
permissions: 0644
rotateeverybytes: 10485760 # 10 MB
logging.metrics.enabled: true
logging.metrics.period: 30s
# ============================== Keystore =================================
# Store sensitive values (passwords, API keys) in the Filebeat keystore
# instead of plaintext in filebeat.yml:
#
# filebeat keystore create
# filebeat keystore add ES_PASSWORD
# filebeat keystore add KAFKA_PASSWORD
#
# Reference in config:
# password: "${ES_PASSWORD}"
Input Types
Filebeat supports multiple input types for different data sources:
| Input Type | Use Case |
|---|---|
log |
Tail regular log files on disk |
container |
Collect Docker or Kubernetes container logs |
stdin |
Read from standard input (testing/piping) |
tcp |
Listen for log events over TCP |
udp |
Listen for log events over UDP |
syslog |
Receive syslog messages (RFC 3164 / RFC 5424) |
journald |
Collect systemd journal entries |
aws-s3 |
Read logs from AWS S3 buckets |
Multiline Settings
Many applications produce log entries that span multiple lines (Java stack traces, JSON payloads). Use multiline settings to merge them into a single event.
# Example: Java stack trace — lines not starting with a timestamp
# are appended to the previous line
filebeat.inputs:
- type: log
paths:
- /var/log/java-app/*.log
multiline.type: pattern
multiline.pattern: '^\d{4}-\d{2}-\d{2}[T ]'
multiline.negate: true
multiline.match: after
multiline.max_lines: 100
multiline.timeout: 10s
Pattern logic:
negate: true+match: after→ Lines that do not match the pattern are appended to the previous linenegate: false+match: before→ Lines that do match are prepended to the next line
Harvester and Registry
The harvester is the core reading mechanism. One harvester is started per file. It opens the file, reads it line by line, and sends content to the output.
The registry file (data/registry/filebeat/log.json) stores the state of every file Filebeat is tracking:
[
{
"source": "/var/log/myapp/app.log",
"offset": 28456,
"timestamp": "2026-04-01T14:44:00.000Z",
"ttl": -1,
"type": "log",
"FileStateOS": {
"inode": 1234567,
"device": 64768
}
}
]
If Filebeat restarts, it reads the registry and resumes from the last known offset — ensuring no log lines are duplicated or lost.
Filebeat Keystore
Store sensitive values securely instead of putting them in plaintext config:
# Create the keystore
filebeat keystore create
# Add a secret
filebeat keystore add ES_PASSWORD
# (You will be prompted to enter the value)
# List stored keys
filebeat keystore list
# Remove a key
filebeat keystore remove ES_PASSWORD
Reference keystore values in filebeat.yml:
output.elasticsearch:
hosts: ["https://es-node-1:9200"]
username: "filebeat_writer"
password: "${ES_PASSWORD}"
Starting and Managing Filebeat
# Test configuration
filebeat test config -e
# Test output connectivity
filebeat test output
# Start Filebeat (systemd)
sudo systemctl start filebeat
sudo systemctl enable filebeat
# Run in foreground (debug)
filebeat -e -d "*"
# Run with a specific config
filebeat -e -c /etc/filebeat/custom.yml
Quick Reference
| Task | Command / Config |
|---|---|
| Install (Debian) | sudo dpkg -i filebeat-8.17.0-amd64.deb |
| Config file | /etc/filebeat/filebeat.yml |
| Data/registry | /var/lib/filebeat/registry/ |
| Test config | filebeat test config -e |
| Test output | filebeat test output |
| Start service | sudo systemctl start filebeat |
| Enable on boot | sudo systemctl enable filebeat |
| View logs | journalctl -u filebeat -f |
| Keystore create | filebeat keystore create |
| Add secret | filebeat keystore add KEY_NAME |
Next: Filebeat Modules — pre-built configurations for common log formats.