Shipping application logs into a Logstash pipeline turns plain text files on disk into searchable events, which is a common starting point for centralizing custom application logs, legacy daemon output, or local logs that are not already forwarded by another shipper.
The file input has two operating modes. tail mode, which Elastic still documents as the default, keeps watching files as they grow and emits each new line, while read mode treats each file as content-complete input and finishes at end of file. For continuously growing application logs, an absolute path, explicit tail mode, and a dedicated sincedb file keep ingestion predictable across restarts and log rotation.
start_position set to beginning only affects a file the first time Logstash sees it without an existing sincedb record. Reusing a sincedb_path across inputs, watching files the logstash service account cannot read, or pointing the input at rotated archives are the most common reasons a new file input appears to skip lines or replay old ones.
input {
file {
path => ["/var/log/app/*.log"]
exclude => ["*.gz"]
mode => "tail"
start_position => "beginning"
sincedb_path => "/var/lib/logstash/file-input-app.sincedb"
}
}
output {
elasticsearch {
hosts => ["http://elasticsearch.example.net:9200"]
index => "app-logs-%{+YYYY.MM.dd}"
}
}
Current Elastic documentation still requires the path value to be absolute. Setting mode to tail explicitly keeps the pipeline intent clear and avoids confusion with read mode examples that process content-complete files.
Use a different sincedb_path for each file input. Elastic's current plugin reference states that sincedb_path must point to a file, not a directory.
start_position only changes first-contact behavior for files without an existing sincedb entry. Removing or reusing the sincedb file can replay older log lines and duplicate events downstream.
$ sudo ls -1 /var/log/app/*.log /var/log/app/app-error.log /var/log/app/app.log
If rotated archives stay in the same directory, keeping exclude ⇒ [“*.gz”] prevents compressed copies from being picked up as fresh input.
$ sudo -u logstash tail -n 1 /var/log/app/app.log 2026-04-07T08:35:29Z INFO request_id=9b2a5f2c status=200 path=/health
Both the file and every parent directory in its path need permissions that let the logstash user traverse the directory tree and read the file.
$ sudo /usr/share/logstash/bin/logstash --path.settings /etc/logstash --config.test_and_exit Using bundled JDK: /usr/share/logstash/jdk ##### snipped ##### Configuration OK [2026-04-07T08:36:32,784][INFO ][logstash.runner ] Using config.test_and_exit mode. Config Validation Result: OK. Exiting Logstash
$ sudo systemctl restart logstash
$ sudo systemctl status logstash
● logstash.service - logstash
Loaded: loaded (/etc/systemd/system/logstash.service; enabled; preset: enabled)
Active: active (running) since Tue 2026-04-07 16:35:28 +08; 3s ago
##### snipped #####
$ sudo ls -l /var/lib/logstash/file-input-app.sincedb -rw------- 1 logstash logstash 113 Apr 7 16:35 /var/lib/logstash/file-input-app.sincedb
Elastic currently documents the default sincedb location under <path.data>/plugins/inputs/file. Setting sincedb_path explicitly keeps the tracked offset file predictable for this pipeline, and the timestamp should change after new lines are consumed.
Elastic also notes that remote filesystems are not thoroughly tested for this input. Keep watched logs on a stable local filesystem when possible to avoid misleading file identity or offset state.