Sending parsed events from Logstash to Elasticsearch turns an ingest pipeline into searchable documents for dashboards, alerts, and retention policies. The output block decides which cluster receives the events, how Logstash authenticates, and which index name is created when new documents are written.

The elasticsearch output plugin sends batches through the Elasticsearch Bulk API to one or more HTTP(S) endpoints. This configuration uses index mode with an explicit daily index pattern so the destination stays easy to check with a read-only count query.

Modern Logstash releases use ssl_enabled and ssl_certificate_authorities for TLS trust, and packaged 9.x installs block superuser runs unless allow_superuser is changed. Keep the output password in the Logstash keystore, and pair a custom index pattern with ilm_enabled ⇒ false when daily index names must not be replaced by an ILM rollover alias.

Steps to configure Logstash output to Elasticsearch:

  1. Confirm the endpoint, trust file, credential name, and index pattern to use.
    Elasticsearch URL: https://elasticsearch.example.net:9200
    CA certificate: /etc/logstash/certs/http_ca.crt
    Output user: logstash_internal
    Index pattern: logs-%{+YYYY.MM.dd}

    The hosts value should point at Elasticsearch HTTP nodes, not dedicated master-only nodes. Use a read-only account later for the verification query instead of reusing the write-only output account.

  2. Store the output user's password in the Logstash keystore.
    $ sudo /usr/share/logstash/bin/logstash-keystore --path.settings /etc/logstash add LOGSTASH_INTERNAL_PASSWORD
    Enter value for LOGSTASH_INTERNAL_PASSWORD:
    Added 'LOGSTASH_INTERNAL_PASSWORD' to the Logstash keystore.

    The key name must match the ${LOGSTASH_INTERNAL_PASSWORD} placeholder used in the pipeline file.

  3. Create or update the Elasticsearch output block in /etc/logstash/conf.d/30-output.conf.
    output {
      elasticsearch {
        hosts => ["https://elasticsearch.example.net:9200"]
        ssl_enabled => true
        ssl_certificate_authorities => ["/etc/logstash/certs/http_ca.crt"]
        user => "logstash_internal"
        password => "${LOGSTASH_INTERNAL_PASSWORD}"
        ilm_enabled => false
        index => "logs-%{+YYYY.MM.dd}"
      }
    }

    Use a higher numeric prefix such as 30-output.conf so the output block loads after lower-numbered inputs and filters. Use ssl_certificate_authorities for a private or self-signed Elasticsearch HTTP CA; on Elastic Cloud, use cloud_id plus cloud_auth or api_key instead of the self-managed host and CA settings.

  4. Test the pipeline configuration as the logstash service user.
    $ sudo -u logstash /usr/share/logstash/bin/logstash --path.settings /etc/logstash --path.data /tmp/logstash-output-configtest --config.test_and_exit
    Using bundled JDK: /usr/share/logstash/jdk
    Configuration OK
    [2026-06-18T15:20:00,000][INFO ][logstash.runner          ] Using config.test_and_exit mode. Config Validation Result: OK. Exiting Logstash

    The temporary --path.data directory must be writable by the logstash user. This validation confirms pipeline syntax and plugin settings only; it does not prove credentials, TLS trust, or index privileges until the service starts and sends events.

  5. Remove the temporary validation data path.
    $ sudo rm -rf /tmp/logstash-output-configtest
  6. Restart the Logstash service so the updated pipeline is loaded.
    $ sudo systemctl restart logstash

    Restarting Logstash briefly stops pipeline workers and can pause ingestion while outputs reconnect and queues drain.

  7. Review recent service logs for output startup, authentication, or TLS failures.
    $ sudo journalctl --unit logstash --since "5 minutes ago" --no-pager
    Jun 18 15:20:01 logstash-node logstash[24814]: [2026-06-18T15:20:01,510][INFO ][logstash.outputs.elasticsearch][main] Elasticsearch pool URLs updated {changes: {removed: [], added: [https://elasticsearch.example.net:9200/]}}
    Jun 18 15:20:01 logstash-node logstash[24814]: [2026-06-18T15:20:01,681][INFO ][logstash.outputs.elasticsearch][main] Connected to ES instance {url: "https://elasticsearch.example.net:9200/"}
    Jun 18 15:20:01 logstash-node logstash[24814]: [2026-06-18T15:20:01,742][INFO ][logstash.outputs.elasticsearch][main] Data streams auto configuration (`data_stream => auto` or unset) resolved to `false`
    Jun 18 15:20:02 logstash-node logstash[24814]: [2026-06-18T15:20:02,125][INFO ][logstash.javapipeline    ][main] Pipeline started {"pipeline.id"=>"main"}

    401 or 403 responses usually mean the output credential is missing the required role or index privileges, while TLS failures usually mention certificate trust, hostname mismatch, or protocol negotiation.

  8. Verify documents are reaching the expected index pattern with a separate read-capable credential.
    $ curl --silent --show-error --fail \
      --cacert /etc/logstash/certs/http_ca.crt \
      --user reader_user:reader-password \
      "https://elasticsearch.example.net:9200/logs-*/_count?pretty"
    {
      "count" : 42,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      }
    }

    A nonzero count with failed shards at 0 confirms Elasticsearch can read documents from the target index pattern. If the count remains 0, send a fresh event through the pipeline and review the Logstash journal for bulk indexing, template, or lifecycle errors.