A Logstash udp input is useful when an application, appliance, or quick test sender can emit datagrams but does not need a persistent connection. It fits lightweight event delivery, custom JSON emitters, and simple fire-and-forget forwarding where sender overhead needs to stay low.
Current Elastic plugin docs still describe the udp input as a listener that requires only a port, binds to the configured host, decodes payloads with an input codec, and adds the sender IP address as event metadata. On package installs, the active settings still live under /etc/logstash, and pipeline files under /etc/logstash/conf.d are typically loaded into the main pipeline unless a different layout is configured.
UDP is connectionless, so packet loss, duplication, and out-of-order delivery are still possible under congestion. The plugin also drops datagrams when its in-memory queue fills, ports below 1024 may require elevated privileges, and current Logstash releases block superuser starts unless allow_superuser is enabled, so the first validation run is safer on an unprivileged localhost port with the service managed by systemd.
Steps to configure a Logstash UDP input:
- Confirm that the planned UDP port is not already in use.
$ sudo ss -lnup | grep -F ':5515'
No output usually means port 5515 is free.
Ports below 1024, including the traditional syslog UDP port 514, are privileged and can prevent Logstash from starting when the packaged service runs as a non-root account.
- Create a dedicated pipeline file for the UDP listener.
input { udp { id => "udp_json_5515" host => "127.0.0.1" port => 5515 codec => json source_ip_fieldname => "[observer][ingress][ip]" } } output { stdout { id => "stdout_udp_debug" codec => rubydebug } }The current plugin documentation still lists codec defaulting to plain, so keep json only when each datagram is one complete JSON document.
The explicit input id keeps the monitoring API readable, and source_ip_fieldname stores the packet source address away from the event root so sender fields do not collide with a legacy root-level host field.
The temporary stdout output keeps the first validation focused on whether the UDP listener is receiving and decoding events at all. Replace it with the real output after the listener works.
Binding to 127.0.0.1 keeps the first test local. Change it to the required service address or 0.0.0.0 only after validation succeeds, and pair that wider bind with firewall rules. If bursts can exceed the default in-memory queue, tune queue_size and optionally receive_buffer_bytes before exposing the listener to busy senders.
- Test the pipeline file with the packaged settings directory and a temporary data path.
$ sudo -u logstash /usr/share/logstash/bin/logstash \ --path.settings /etc/logstash \ --path.data /tmp/logstash-udp-input-configtest \ --config.test_and_exit \ -f /etc/logstash/conf.d/27-udp-input.conf Using bundled JDK: /usr/share/logstash/jdk [2026-04-08T14:18:41,106][WARN ][logstash.config.source.multilocal] Ignoring the 'pipelines.yml' file because command line options are specified Configuration OK [2026-04-08T14:18:41,941][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 user running the check and keeps the validation away from the service data directory in /var/lib/logstash.
--config.test_and_exit validates syntax and settings assembly only. It does not prove that later network paths, real outputs, or sender payloads will succeed at runtime.
Current Logstash settings still default allow_superuser to false, so run this validation as the logstash service account unless that setting was intentionally changed.
- Restart the Logstash service so it loads the UDP pipeline.
$ sudo systemctl restart logstash.service
Restarting the service pauses every active pipeline briefly while inputs reopen and outputs reconnect.
- Confirm that the Logstash service returned to the running state.
$ sudo systemctl is-active logstash.service active
If the command returns failed or stays in activating too long, inspect sudo journalctl --unit=logstash.service --no-pager --lines=80 before sending any test datagrams.
- Verify that the udp listener is bound to port 5515.
$ sudo ss -lnup | grep -F ':5515' UNCONN 0 0 127.0.0.1:5515 0.0.0.0:* users:(("java",pid=22164,fd=196))If the host value was changed to a service address or 0.0.0.0, the bind target shown by ss should match that configured address.
- Send a single JSON test datagram to the new listener.
$ printf '{"message":"udp input validation","service":"billing","level":"info"}' | nc -u -w 1 127.0.0.1 5515For this validation flow, one datagram becomes one event. Replace 127.0.0.1 with the real Logstash address when testing from another host.
- Query the Logstash monitoring API and confirm that the named UDP input handled the event.
$ curl -s http://127.0.0.1:9600/_node/stats/pipelines/main?pretty { "pipelines" : { "main" : { "events" : { "filtered" : 1, "in" : 1, "out" : 1 }, "plugins" : { "inputs" : [ { "id" : "udp_json_5515", "name" : "udp", "events" : { "out" : 1 } } ] } } } }The explicit input id keeps the input counters readable when the same pipeline contains multiple listeners. If the active pipeline ID is not main, replace it in the API path.
The monitoring API defaults to loopback on current package installs, so query it locally unless the API host or port range was changed in /etc/logstash/logstash.yml.
- Review recent journal lines for listener startup and the decoded event.
$ sudo journalctl --unit=logstash.service --since "5 minutes ago" --no-pager --lines=40 Apr 08 14:21:05 logstash-01 logstash[22164]: [2026-04-08T14:21:05,368][INFO ][logstash.inputs.udp ][main][udp_json_5515] Starting UDP listener {:address=>"127.0.0.1:5515"} Apr 08 14:21:24 logstash-01 logstash[22164]: { Apr 08 14:21:24 logstash-01 logstash[22164]: "message" => "udp input validation", Apr 08 14:21:24 logstash-01 logstash[22164]: "service" => "billing", Apr 08 14:21:24 logstash-01 logstash[22164]: "level" => "info", Apr 08 14:21:24 logstash-01 logstash[22164]: "observer" => { Apr 08 14:21:24 logstash-01 logstash[22164]: "ingress" => { Apr 08 14:21:24 logstash-01 logstash[22164]: "ip" => "127.0.0.1" Apr 08 14:21:24 logstash-01 logstash[22164]: } Apr 08 14:21:24 logstash-01 logstash[22164]: } Apr 08 14:21:24 logstash-01 logstash[22164]: }With the temporary stdout output shown earlier, the journal is usually the quickest place to confirm that the UDP payload was decoded the way the pipeline expects on a package-managed host.
After the listener works, replace the temporary stdout output with the real output section and re-run the same config test before the next restart.
Related: How to configure a Logstash stdout output
Related: How to configure Logstash pipelines
Related: How to debug Logstash pipelines
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.
