OpenSearch configuration
Environment variables
Open the service details (the "..." button, then Details) to see the variables it provides. With the default prefix DEFAULT, your application receives values like the following:
# Backend configuration
DEFAULT_SEARCH_BACKEND=opensearch-multi-index
DEFAULT_SEARCH_AUTH_SCHEME=aws-v4-auth
DEFAULT_SEARCH_VERSION=3.7.0
# Connection details
DEFAULT_SEARCH_HOSTNAME=search-cluster-psckcd7m2b6d5iiijunwsyvo34.eu-central-1.es.amazonaws.com
DEFAULT_SEARCH_PORT=443
DEFAULT_SEARCH_ACCESS_KEY_ID=AKIA...
DEFAULT_SEARCH_SECRET_ACCESS_KEY=SECRET...
# Full connection string and Haystack URL (credentials are URL-encoded)
DEFAULT_SEARCH_DSN=https://AKIA...:SECRET...@search-cluster-psckcd7m2b6d5iiijunwsyvo34.eu-central-1.es.amazonaws.com:443/myapp-live-7303e23cd7e9497aa6b25789c5a6e6-be706cf-*
DEFAULT_SEARCH_HAYSTACK_URL=es+https+aws://AKIA...:SECRET...@search-cluster-psckcd7m2b6d5iiijunwsyvo34.eu-central-1.es.amazonaws.com:443/myapp-live-7303e23cd7e9497aa6b25789c5a6e6-be706cf-*
# Index prefix constraint
DEFAULT_SEARCH_INDEX_PREFIX=myapp-live-7303e23cd7e9497aa6b25789c5a6e6-be706cf-*
If you use a different prefix, replace DEFAULT_ with your own prefix.
We recommend building the connection from the individual variables rather than parsing the DSN.
Authentication
Authentication is AWS SigV4 (IAM), not HTTP basic authentication.
DEFAULT_SEARCH_ACCESS_KEY_ID and DEFAULT_SEARCH_SECRET_ACCESS_KEY are AWS IAM credentials, and they are used to sign each request. You cannot pass them as a username and password, even though they appear inside the DSN.
Most OpenSearch clients support this out of the box. In Python, opensearch-py provides AWSV4SignerAuth, which needs to be paired with RequestsHttpConnection. See the configuration examples.
Index naming rules
DEFAULT_SEARCH_INDEX_PREFIX is a pattern, not an index name. It ends with * and describes every index your application is allowed to touch.
Index names cannot contain *, so your application has to build a real name by removing the wildcard and adding its own suffix:
prefix = os.environ["DEFAULT_SEARCH_INDEX_PREFIX"].rstrip("*")
index_name = f"{prefix}default" # myapp-live-...-be706cf-default
Your credentials only allow index names that match the pattern:
| Index name | Result |
|---|---|
myapp-live-7303e23cd7e9497aa6b25789c5a6e6-be706cf-default | allowed |
myapp-live-7303e23cd7e9497aa6b25789c5a6e6-be706cf-another-index | allowed |
default | denied |
myapp-test-7303e23cd7e9497aa6b25789c5a6e6-ab3121a-index | denied |
anotherapp-live-123afde4de3321afe45610eabce234-ab3121a-default | denied |
The reason for this restriction is that the AWS permissions model could otherwise allow aliases to bypass the intended access restrictions.
Cluster limitations
Applications share a managed cluster, and your credentials are scoped to your index prefix. Cluster-level API paths are therefore not available to your application:
GET /is denied, and so are/_cluster/healthand/_cat/indices. Anything that reads cluster information or cluster health as a readiness check will getHTTP 403. Point health checks at your own index instead, for example a_counton it.- Searches must name an index.
POST /_searchwithout an index, and/_all/_search, are denied. Libraries such as Haystack always address the index by name, so this only affects hand-written queries. - The scroll API (
/_search/scroll) is not available. Instead, use thesortparameter with thesearch_afterparameter to scroll responses for user queries.
If you need cluster-level access, a dedicated cluster is required. Contact our support team.
Troubleshooting
| Symptom | Likely cause |
|---|---|
HTTP 403 on indexing, empty index after rebuild_index | the request went to a cluster-level endpoint (/_bulk, /_search) instead of your index, or the index name is outside your prefix |
HTTP 403 on a health check | the check reads GET /, /_cluster/health or /_cat/indices. Use a _count on your own index instead |
UnsupportedProductError, or the client refuses to connect | an Elasticsearch client is being used instead of an OpenSearch one. elasticsearch-py 7.14 and later run a product check against the server, and 8.x fails outright |
| Invalid index name error | the index name still contains the * from DEFAULT_SEARCH_INDEX_PREFIX |
| Autocomplete returns nothing | the mapping lost its analyzer on EdgeNgramField or NgramField. See the fixes in the Django section |
HTTP 400 when sorting or faceting | you are sorting or faceting on an analyzed text field. Declare the field with faceted=True and use the <field>_exact keyword field, or sort on a date or integer field |
HTTP 400 mentioning types or doc_type | mapping types no longer exist. They were removed in Elasticsearch 7 and OpenSearch never supported them |
If you need support, contact us.