ELK Stack — Backup & Restore
Backup & Restore in Elasticsearch
Elasticsearch snapshots are the only reliable way to back up a cluster. Snapshots capture the state of indices, data streams, and cluster metadata at a point in time and store them in an external repository. This section covers repository types, creating and restoring snapshots, and automating the entire process with Snapshot Lifecycle Management (SLM).
Snapshot Repository Types
| Type | Plugin Required | Use Case |
|---|---|---|
Shared file system (fs) |
None | NFS mount shared across all nodes |
| AWS S3 | repository-s3 |
Cloud-native backup on AWS |
| Google Cloud Storage | repository-gcs |
Cloud-native backup on GCP |
| Azure Blob Storage | repository-azure |
Cloud-native backup on Azure |
| HDFS | repository-hdfs |
Hadoop environments |
Tip: Always prefer object-store repositories (S3, GCS, Azure) over shared filesystems in production. They scale better and eliminate the NFS single point of failure.
Registering a Snapshot Repository
Shared File System
Every node must have the path registered in elasticsearch.yml:
# elasticsearch.yml
path.repo: ["/mnt/es-snapshots"]
Register the repository:
curl -X PUT "localhost:9200/_snapshot/my_fs_repo" -H 'Content-Type: application/json' -d'
{
"type": "fs",
"settings": {
"location": "/mnt/es-snapshots",
"compress": true,
"max_snapshot_bytes_per_sec": "200mb",
"max_restore_bytes_per_sec": "200mb"
}
}'
AWS S3
Install the plugin on every node:
bin/elasticsearch-plugin install repository-s3
Add credentials to the Elasticsearch keystore:
bin/elasticsearch-keystore add s3.client.default.access_key
bin/elasticsearch-keystore add s3.client.default.secret_key
Register the repository:
curl -X PUT "localhost:9200/_snapshot/my_s3_repo" -H 'Content-Type: application/json' -d'
{
"type": "s3",
"settings": {
"bucket": "my-es-snapshots",
"region": "us-east-1",
"base_path": "production",
"compress": true,
"server_side_encryption": true,
"storage_class": "standard_ia"
}
}'
Google Cloud Storage
bin/elasticsearch-plugin install repository-gcs
bin/elasticsearch-keystore add-file gcs.client.default.credentials_file /path/to/service-account.json
curl -X PUT "localhost:9200/_snapshot/my_gcs_repo" -H 'Content-Type: application/json' -d'
{
"type": "gcs",
"settings": {
"bucket": "my-es-snapshots",
"base_path": "production",
"compress": true
}
}'
Azure Blob Storage
bin/elasticsearch-plugin install repository-azure
bin/elasticsearch-keystore add azure.client.default.account
bin/elasticsearch-keystore add azure.client.default.key
curl -X PUT "localhost:9200/_snapshot/my_azure_repo" -H 'Content-Type: application/json' -d'
{
"type": "azure",
"settings": {
"container": "es-snapshots",
"base_path": "production",
"compress": true
}
}'
Creating Snapshots
Full Cluster Snapshot
curl -X PUT "localhost:9200/_snapshot/my_s3_repo/snapshot-$(date +%Y%m%d-%H%M%S)?wait_for_completion=false"
Snapshot Specific Indices
curl -X PUT "localhost:9200/_snapshot/my_s3_repo/logs-snapshot-2026-04" -H 'Content-Type: application/json' -d'
{
"indices": "logs-2026.04.*",
"ignore_unavailable": true,
"include_global_state": false
}'
Snapshot Data Streams
curl -X PUT "localhost:9200/_snapshot/my_s3_repo/ds-snapshot" -H 'Content-Type: application/json' -d'
{
"indices": "logs-*",
"include_global_state": false,
"feature_states": ["none"]
}'
Snapshot Lifecycle Management (SLM)
SLM automates snapshot creation, retention, and deletion on a schedule.
Create an SLM Policy
curl -X PUT "localhost:9200/_slm/policy/nightly-snapshots" -H 'Content-Type: application/json' -d'
{
"schedule": "0 30 2 * * ?",
"name": "<nightly-snap-{now/d}>",
"repository": "my_s3_repo",
"config": {
"indices": ["*"],
"ignore_unavailable": true,
"include_global_state": false
},
"retention": {
"expire_after": "30d",
"min_count": 5,
"max_count": 50
}
}'
The schedule uses a cron expression — 0 30 2 * * ? runs at 02:30 UTC daily.
Execute a Policy Immediately
curl -X POST "localhost:9200/_slm/policy/nightly-snapshots/_execute"
View SLM Policy Status
curl -s "localhost:9200/_slm/policy/nightly-snapshots" | jq .
View SLM Stats
curl -s "localhost:9200/_slm/stats" | jq .
Restoring Snapshots
Full Restore
curl -X POST "localhost:9200/_snapshot/my_s3_repo/nightly-snap-2026.04.01/_restore" -H 'Content-Type: application/json' -d'
{
"indices": "*",
"include_global_state": true
}'
Partial Restore (Specific Indices)
curl -X POST "localhost:9200/_snapshot/my_s3_repo/nightly-snap-2026.04.01/_restore" -H 'Content-Type: application/json' -d'
{
"indices": "logs-2026.03.*",
"ignore_unavailable": true,
"include_global_state": false
}'
Restore with Rename
Useful when restoring to the same cluster without deleting the original index:
curl -X POST "localhost:9200/_snapshot/my_s3_repo/nightly-snap-2026.04.01/_restore" -H 'Content-Type: application/json' -d'
{
"indices": "logs-2026.03.31",
"rename_pattern": "(.+)",
"rename_replacement": "restored-$1",
"include_global_state": false
}'
Restore to a Different Cluster
- Register the same repository on the target cluster (point to the same S3 bucket/path).
- List available snapshots:
GET _snapshot/my_s3_repo/* - Restore as above.
Important: The target cluster must be the same or newer major version as the cluster that created the snapshot.
Snapshot Status & Monitoring
Check Snapshot Progress
curl -s "localhost:9200/_snapshot/my_s3_repo/nightly-snap-2026.04.01/_status" | jq .
Response includes shard-level progress:
{
"snapshots": [{
"snapshot": "nightly-snap-2026.04.01",
"state": "IN_PROGRESS",
"shards_stats": {
"total": 50,
"done": 35,
"started": 15
}
}]
}
List All Snapshots
curl -s "localhost:9200/_snapshot/my_s3_repo/*?verbose=false" | jq '.snapshots | length'
Delete Old Snapshots
curl -X DELETE "localhost:9200/_snapshot/my_s3_repo/nightly-snap-2026.03.01"
Searchable Snapshots
Searchable snapshots let you query data directly from the snapshot repository without fully restoring it, saving storage on your data nodes.
Mount a Searchable Snapshot
curl -X POST "localhost:9200/_snapshot/my_s3_repo/nightly-snap-2026.04.01/_mount?storage=shared_cache" -H 'Content-Type: application/json' -d'
{
"index": "logs-2026.03.01",
"renamed_index": "searchable-logs-2026.03.01"
}'
Storage options:
full_copy— Downloads all data to local storage (fast, uses more disk).shared_cache— Uses a local cache; fetches from the repository on demand (slower, uses less disk).
Quick Reference
| Task | Command |
|---|---|
| Register FS repository | PUT _snapshot/repo { "type": "fs", ... } |
| Register S3 repository | PUT _snapshot/repo { "type": "s3", ... } |
| Create snapshot | PUT _snapshot/repo/snap_name |
| Create SLM policy | PUT _slm/policy/policy_name { ... } |
| Execute SLM now | POST _slm/policy/policy_name/_execute |
| Restore snapshot | POST _snapshot/repo/snap_name/_restore |
| Restore with rename | Add rename_pattern + rename_replacement |
| Check snapshot status | GET _snapshot/repo/snap_name/_status |
| Mount searchable snapshot | POST _snapshot/repo/snap_name/_mount |
| Delete snapshot | DELETE _snapshot/repo/snap_name |
| SLM stats | GET _slm/stats |
Next Steps
Backups protect against data loss, but you also need to know when something is going wrong before it becomes an emergency. Continue to Cluster Monitoring.