ELK Stack — Enabling Security
Enabling Security
Elasticsearch 8.x ships with security enabled by default. When you start Elasticsearch for the first time it automatically generates certificates, creates the elastic superuser with a random password, and produces enrollment tokens for Kibana and other nodes.
If you are running Elasticsearch 7.x or have an existing cluster without security, you must enable it manually.
Security Enabled by Default (ES 8.x)
On a fresh Elasticsearch 8.x installation the first-start output looks like this:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ Elasticsearch security features have been automatically configured!
→ Authentication is enabled and cluster connections are encrypted.
🔑 Password for the elastic user:
<auto-generated-password>
🔗 Kibana enrollment token (valid for 30 minutes):
eyJ2ZXIiOiI4LjE1LjAiLCJhZHIiOi...
🔗 Node enrollment token (valid for 30 minutes):
eyJ2ZXIiOiI4LjE1LjAiLCJhZHIiOi...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Save these values immediately — you will need them to enroll Kibana and additional nodes.
Enabling Security on an Existing Cluster
If security was not enabled at install time, add the following to elasticsearch.yml on every node:
# /etc/elasticsearch/elasticsearch.yml
xpack.security.enabled: true
xpack.security.enrollment.enabled: true
# Transport layer encryption (required when security is enabled)
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.verification_mode: certificate
xpack.security.transport.ssl.keystore.path: certs/transport.p12
xpack.security.transport.ssl.truststore.path: certs/transport.p12
# HTTP layer encryption
xpack.security.http.ssl.enabled: true
xpack.security.http.ssl.keystore.path: certs/http.p12
Important: You must generate TLS certificates before restarting. See the TLS/SSL page for the full process.
Restart the cluster one node at a time (rolling restart):
sudo systemctl restart elasticsearch
Enrollment Tokens
Enrollment tokens simplify adding Kibana instances and new Elasticsearch nodes to a secured cluster.
Generate a Kibana enrollment token:
/usr/share/elasticsearch/bin/elasticsearch-create-enrollment-token -s kibana
Generate a node enrollment token:
/usr/share/elasticsearch/bin/elasticsearch-create-enrollment-token -s node
Tokens expire after 30 minutes by default. You can regenerate them at any time.
Setting Passwords with elasticsearch-setup-passwords
For clusters upgraded from 7.x you can set passwords for all built-in users interactively:
/usr/share/elasticsearch/bin/elasticsearch-setup-passwords interactive
Output:
Initiating the setup of passwords for reserved users.
You will be prompted to enter passwords as the process progresses.
Enter password for [elastic]:
Reenter password for [elastic]:
Enter password for [apm_system]:
Reenter password for [apm_system]:
Enter password for [kibana_system]:
Reenter password for [kibana_system]:
Enter password for [logstash_system]:
Reenter password for [logstash_system]:
Enter password for [beats_system]:
Reenter password for [beats_system]:
Enter password for [remote_monitoring_user]:
Reenter password for [remote_monitoring_user]:
Changed password for user [elastic]
Changed password for user [apm_system]
Changed password for user [kibana_system]
Changed password for user [logstash_system]
Changed password for user [beats_system]
Changed password for user [remote_monitoring_user]
This command can only be run once. Use
elasticsearch-reset-passwordafterwards.
Resetting Passwords
Reset a password for any built-in user at any time:
# Auto-generate a new password
/usr/share/elasticsearch/bin/elasticsearch-reset-password -u elastic
# Set a specific password interactively
/usr/share/elasticsearch/bin/elasticsearch-reset-password -u elastic -i
Output:
Password for the [elastic] user successfully reset.
New value: Kx9q_T2bRwZ=aJnPm5vL
Configuring the kibana_system User for Kibana
Kibana connects to Elasticsearch using the kibana_system user. Add the credentials to kibana.yml:
# /etc/kibana/kibana.yml
elasticsearch.username: "kibana_system"
elasticsearch.password: "your-kibana-system-password"
Alternatively, store the password in the Kibana keystore:
/usr/share/kibana/bin/kibana-keystore add elasticsearch.password
Restart Kibana:
sudo systemctl restart kibana
Configuring Logstash to Authenticate
Logstash needs credentials for its Elasticsearch output plugin:
# /etc/logstash/conf.d/output.conf
output {
elasticsearch {
hosts => ["https://es-node-1:9200"]
user => "logstash_writer"
password => "strong-password-here"
ssl_enabled => true
ssl_certificate_authorities => ["/etc/logstash/certs/ca.crt"]
}
}
Create a dedicated logstash_writer role and user:
# Create the role
curl -k -u elastic:password -X POST "https://localhost:9200/_security/role/logstash_writer" \
-H "Content-Type: application/json" -d'
{
"cluster": ["manage_index_templates", "monitor", "manage_ilm"],
"indices": [
{
"names": ["logstash-*", "logs-*"],
"privileges": ["write", "create_index", "manage", "auto_configure"]
}
]
}'
# Create the user
curl -k -u elastic:password -X POST "https://localhost:9200/_security/user/logstash_writer" \
-H "Content-Type: application/json" -d'
{
"password": "strong-password-here",
"roles": ["logstash_writer"],
"full_name": "Logstash Writer"
}'
Configuring Beats to Authenticate
Filebeat and other Beats agents need credentials to send data to Elasticsearch:
# /etc/filebeat/filebeat.yml
output.elasticsearch:
hosts: ["https://es-node-1:9200"]
username: "filebeat_writer"
password: "strong-password-here"
ssl:
enabled: true
certificate_authorities: ["/etc/filebeat/certs/ca.crt"]
Create a dedicated Beats user:
curl -k -u elastic:password -X POST "https://localhost:9200/_security/user/filebeat_writer" \
-H "Content-Type: application/json" -d'
{
"password": "strong-password-here",
"roles": ["editor"],
"full_name": "Filebeat Writer"
}'
Verifying Security Is Working
1. Test without credentials (should fail):
curl -k https://localhost:9200/
Response:
{
"error": {
"type": "security_exception",
"reason": "missing authentication credentials for REST request [/]"
},
"status": 401
}
2. Test with valid credentials (should succeed):
curl -k -u elastic:your-password https://localhost:9200/
Response:
{
"name": "es-node-1",
"cluster_name": "production",
"cluster_uuid": "abc123",
"version": {
"number": "8.15.0"
},
"tagline": "You Know, for Search"
}
3. Verify authenticated user:
curl -k -u elastic:your-password https://localhost:9200/_security/_authenticate
Response:
{
"username": "elastic",
"roles": ["superuser"],
"full_name": null,
"email": null,
"authentication_realm": {
"name": "reserved",
"type": "reserved"
},
"enabled": true
}
Quick Reference
| Task | Command / Setting |
|---|---|
| Enable security | xpack.security.enabled: true in elasticsearch.yml |
| Generate Kibana enrollment token | elasticsearch-create-enrollment-token -s kibana |
| Generate node enrollment token | elasticsearch-create-enrollment-token -s node |
| Set built-in passwords (first time) | elasticsearch-setup-passwords interactive |
| Reset a user password | elasticsearch-reset-password -u <user> |
| Configure Kibana credentials | elasticsearch.username / elasticsearch.password in kibana.yml |
| Logstash authentication | user / password in elasticsearch output plugin |
| Beats authentication | username / password under output.elasticsearch |
| Verify authentication | curl -u user:pass https://host:9200/_security/_authenticate |
Next: TLS/SSL — encrypt all communication in your cluster.