Open-source project
elastic/curator avatar
elastic/curator

Elasticsearch Curator: index lifecycle management from a YAML action file

Curator: Tending your Elasticsearch indices

3,079 stars626 forksPythonNOASSERTION

At a glance

What is it?
Curator is Elastic's Python tool for deleting, closing, snapshotting and reindexing Elasticsearch indices on a schedule. It is a cron-driven batch job with a declarative action file, not a daemon, and its version line has to match your cluster.
Who is it for?
Adopt Curator if you run Elasticsearch 8.x (or 7.14.0 through 7.17.x on Curator 8.0.18 or newer) and need scheduled deletion, closing, snapshotting or reindexing driven by a file you can review in a pull request. Skip it if you are on Elasticsearch 6.x or 7.0 through 7.13, where the README's version pairing points you at Curator 6.x or 7.x instead, or if you want a long-running service rather than a cron job.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 155 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What Curator solves, and the version pairing you have to respect first

Elasticsearch accumulates indices. Time-series data lands in a new index per day or per rollover, and nothing in the cluster removes the old ones. Curator is the batch tool that does: it connects to a cluster, selects indices by name pattern, age, size or space, and then applies an action such as delete_indices, close, snapshot, forcemerge or reindex. The audience is operations and platform engineers who already run Elasticsearch and want retention expressed as a file under version control rather than a shell script full of curl calls.

The first thing to internalise is that Curator releases are version dependent. The README states the rule plainly: Curator 6.x works with Elasticsearch 6.x, Curator 7.x with Elasticsearch 7.x, and Curator 8.x with Elasticsearch 8.x. There is one documented widening of that rule. Starting with Curator 8.0.18, Curator 8 can execute against Elasticsearch 7.14.0 through 7.17.x in addition to all versions of Elasticsearch 8.x. So a cluster on 7.10 is not covered by Curator 8, and the README points that operator at Curator 7.x. The release list shows v9.0.0 dated 2025-10-03, v8.0.21 dated 2025-04-01 and v8.0.20 dated 2025-03-24, and the repository's last push was on 2026-04-28.

That pairing is the single most common source of confusion, and the README does not spell out a support matrix beyond those sentences. Treat the version rule as a hard gate before you plan anything else.

How Curator connects: the es_client split and the elasticsearch root key

Older Curator releases carried their own client configuration code. That changed. Curator now connects through the es_client Python module, and the README describes the split as making it much easier to update the client connection portion separate from Curator. The practical consequence is visible in pyproject.toml, where the runtime dependency list is a single pinned entry: es_client==8.19.5. There is no separate elasticsearch client pin to reconcile, because es_client owns it.

The configuration file changed shape to match. The README says the updated configuration file structure requires elasticsearch at the root level, with client and other_settings beneath it, and logging as a sibling. The README's own example lists the keys the client block accepts: hosts, cloud_id, bearer_auth, opaque_id, request_timeout, http_compress, verify_certs, ca_certs, client_cert, client_key, ssl_assert_hostname, ssl_assert_fingerprint and ssl_version. Under other_settings it lists master_only, skip_version_test, username, password and a nested api_key with id and api_key.

The logging block carries loglevel, logfile, logformat and a blacklist list. Note the asymmetry the README admits: the action file structure is unchanged, for now, and a few actions may have had the options modified a bit. If you are migrating from an older release, the connection file is where your edits will land, not the action file.

Installing Curator and running a first real action

The package is published as elasticsearch-curator and requires Python 3.8 or newer, per pyproject.toml. Installing it puts three console scripts on your path: curator, curator_cli and es_repo_mgr. The first reads a configuration file plus an action file, the second runs a single action without an action file, and the third manages snapshot repositories.

bash
pip3 install elasticsearch-curator

The Dockerfile builds a frozen binary instead, installing Curator locally with pip3 install . inside the builder stage and copying the frozen result to /curator/ in the published image, where the entrypoint is /curator/curator.

With the package installed, create a configuration file. The README prints this structure, with elasticsearch at the root and logging as a sibling:

yaml
---
elasticsearch:
  client:
    hosts: https://10.11.12.13:9200
    cloud_id:
    bearer_auth:
    opaque_id:
    request_timeout: 60
    http_compress:
    verify_certs:
    ca_certs:
    client_cert:
    client_key:
    ssl_assert_hostname:
    ssl_assert_fingerprint:
    ssl_version:
  other_settings:
    master_only:
    skip_version_test:
    username:
    password:
    api_key:
      id:
      api_key:

logging:
  loglevel: INFO
  logfile: /path/to/file.log
  logformat: default
  blacklist: []

The repository ships worked examples under examples/actions/ and a sample configuration at examples/curator.yml, so start from those rather than inventing keys. The README does not print a complete action file, and it says the action file structure is unchanged, for now; the action names it lists include delete_indices, close, snapshot, forcemerge and reindex. The project's own entry scripts at the top level of the repository are run_curator.py, run_singleton.py and run_es_repo_mgr.py. The command exits without a running process left behind, which is the point: you schedule it, you do not supervise it. Before pointing it at a cluster that holds data you care about, run it against a copy first, because the README does not document a dry-run flag.

Where Curator is the wrong tool, and the failure modes to plan for

Curator is a batch client. It has no daemon, no scheduler and no state of its own. If the cron entry does not fire, nothing happens and nothing tells you. There is no built-in alerting described in the README, so a failed run is visible only through the logfile named in the logging block or through whatever wrapper you put around the exit code.

The second limitation is the version gate described earlier, and it cuts both ways. A cluster upgrade from 7.17 to 8.x can leave you on a Curator release that no longer matches, and the README's announcement section does not describe a migration path beyond the version pairing itself.

Third, the action file is powerful enough to be dangerous. A pattern filter combined with an age filter will delete whatever both match, and Curator does not ask for confirmation. The README does not document rollback. If a delete action selects too broadly, the indices are gone unless you have snapshots, which is why the snapshot action and es_repo_mgr exist as companions rather than optional extras.

Finally, if your retention needs are simple and your cluster is on a recent Elasticsearch release with index lifecycle management available, Curator is a second system to operate. It wins when you need cross-index operations, reindexing, or a reviewable file that describes retention for many index families at once.

Curator against ILM and against hand-written scripts

The obvious alternative is Elasticsearch's own index lifecycle management, which moves through hot, warm, cold and delete phases attached to an index template. The difference in approach is where the policy lives. ILM lives inside the cluster and is applied automatically as indices roll over; Curator lives in a YAML file on a host that runs on a schedule and reaches into the cluster from outside. ILM cannot reindex an arbitrary set of old indices or take a snapshot of a hand-picked list. Curator can, because it is a client with a filter language, not a state machine attached to an index.

The other alternative is a shell script around the Elasticsearch API. That is what Curator replaces. The gain is the filter vocabulary and the action vocabulary combined into one file, plus a packaged form that can run without a Python environment on the host. The cost is a dependency on es_client==8.19.5 and on the version pairing. If your retention rule is one line of curl, Curator is overhead. If it is twenty index families with different ages, the action file earns its place.

Maintenance cost, packaging and the licence situation

The repository is not archived, and its last push was on 2026-04-28. The most recent release in the list is v9.0.0, dated 2025-10-03, following v8.0.21 on 2025-04-01 and v8.0.20 on 2025-03-24. Read that as a project that ships on a slow cadence tied to Elasticsearch major versions rather than a fast-moving library.

The upgrade cost is dominated by the version pairing, not by API churn. The README says the action file structure is unchanged, for now, so most upgrades between releases in the same major line should leave your action files alone. The connection file is the part that moved, and es_client is pinned to an exact version in pyproject.toml, so a Curator upgrade may pull a different es_client with it. Test the connection and a first run against a staging cluster before rolling a new Curator release into a production cron job.

Packaging is offered two ways. The Python package installs with pip and requires Python 3.8 or newer. There is also a Dockerfile that builds a frozen binary with cx_Freeze on Alpine, copies it into a clean alpine image, creates /.curator, and runs as USER nobody:nobody with ENTRYPOINT ["/curator/curator"]. The image is built for a specific architecture because, as the Dockerfile comments note, the architecture appears in the file name, and alpine4docker.sh handles the linking. If you want Curator without a Python environment on the host, that is the route.

On licensing: pyproject.toml declares the classifier License :: OSI Approved :: Apache Software License, while the repository metadata reports the licence as NOASSERTION. The LICENSE and NOTICE files are both present at the top level. Those two signals disagree, and neither the README nor pyproject.toml resolves which text governs. Read LICENSE and NOTICE yourself before you redistribute the package or bake it into an image you ship.

Editorial conclusion

Adopt Curator if you run Elasticsearch 8.x (or 7.14.0 through 7.17.x on Curator 8.0.18 or newer) and need scheduled deletion, closing, snapshotting or reindexing driven by a file you can review in a pull request. Skip it if you are on Elasticsearch 6.x or 7.0 through 7.13, where the README's version pairing points you at Curator 6.x or 7.x instead, or if you want a long-running service rather than a cron job. Before trusting it with production data, verify that the exact Curator release you install is paired with your cluster version and confirm the action file's filters select the indices you think they do.

Frequently asked questions

How do I use Elasticsearch Curator for the first time?

Install elasticsearch-curator, write a configuration file with elasticsearch at the root level, write an action file with at least one action and its filters, then run the curator command with the configuration file and the action file as arguments. The repository ships example action files under examples/actions/ and a sample configuration at examples/curator.yml.

What is Elasticsearch Curator?

It is a Python tool from Elastic that manages Elasticsearch indices and snapshots, selecting them by filters such as pattern, age and space and applying actions such as delete_indices, close, snapshot, forcemerge and reindex. The README describes it as helping you curate, or manage, your indices.

Which Elasticsearch version does Curator work with?

Curator releases are version dependent: Curator 6.x works with Elasticsearch 6.x, Curator 7.x with Elasticsearch 7.x, and Curator 8.x with Elasticsearch 8.x. Starting with Curator 8.0.18, Curator 8 can also execute against Elasticsearch 7.14.0 through 7.17.x.

Which commands does the Elasticsearch Curator package install?

pyproject.toml declares three console scripts: curator, which reads a configuration file and an action file; curator_cli, which runs a single action without an action file; and es_repo_mgr, which manages snapshot repositories. The Docker image instead exposes a frozen binary at /curator/curator.

Does Elasticsearch Curator run as a service?

No. The README describes a command-line tool that executes and exits, so it is normally invoked on a schedule rather than left running. The logging block in the configuration file names a logfile, which is where a scheduled run records what it did.

Official sources

  1. elastic/curator on GitHub
  2. Issues
  3. README
  4. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/elastic-curator.svg)](https://hysenlabs.com/projects/elastic-curator)