DocsGet started
Deploy into your AWS account
One CloudFormation stack creates the server, a data bucket you own, and an admin credential in Secrets Manager.
You need a license keyProduction deployments on AWS require a license. Pilot licenses are free for 30–60 days: request one by email. To try Search without AWS, use the local pilot.
Before you begin
- An AWS account and permission to create a CloudFormation stack with IAM roles, a VPC, EC2, S3 and Secrets Manager resources.
- Your license key, a single line starting with
SL1.. - The IP range allowed to reach the API, for example your office egress address as
203.0.113.10/32. - Optional, for HTTPS: a domain name you control and an ACM certificate for it in the same region.
1. Launch the stack
Opens the AWS console's quick-create page in us-east-1 with the template preloaded. The template is not tied to a region; it looks up the Amazon Linux image in whichever region you use. Launch it in another region: us-east-2, us-west-2, eu-west-1. You can also switch regions in the console header before you choose Create stack. Your data bucket, certificate and license all stay in the region you pick.
Launch StackFill in the parameters below, tick the box that acknowledges IAM resource creation, and choose Create stack.
| Parameter | Default | Notes |
|---|---|---|
LicenseKey | required | Your SL1. license. Hidden in the console (NoEcho). A license may be bound to specific bucket names. |
AllowedCidr | required | Who may reach the API and console. There is deliberately no 0.0.0.0/0 default. Use the narrowest range that works. |
InstanceType | t4g.small | An arm64 Graviton instance type. Choose a larger type for bigger working sets or more concurrent queries. |
DataBucketName | empty | Leave empty to create a new, retained bucket, or name an existing bucket in the same region that uses SSE-S3. |
DomainName, CertificateArn | empty | Set both, or leave both empty. Both set adds an HTTPS load balancer with your ACM certificate. Both empty means the server listens on plain HTTP port 8080. |
Version | current release | The release to install. Change it to upgrade (see below). |
ReleaseSha256 | current release | SHA-256 of the release tarball. The instance refuses a download that does not match. |
HTTP versus HTTPSWithout DomainName and CertificateArn, API keys travel over plain HTTP. That is fine for a short pilot from a single trusted IP. For anything else, set up the HTTPS load balancer.
What the stack creates
- A small VPC with two public subnets (no NAT gateway) and a security group limited to
AllowedCidr. - An S3 data bucket with Block Public Access, SSE-S3 encryption, versioning and a TLS-only policy. It is retained when the stack is deleted.
- One EC2 instance (Amazon Linux 2023, arm64) with IMDSv2 required, an encrypted gp3 cache volume, and an Elastic IP. Administrative access is through SSM Session Manager. There is no SSH.
- An instance role scoped to the data bucket, a Secrets Manager secret with a generated admin credential, and a CloudWatch log group.
- If requested, an Application Load Balancer with an HTTPS listener.
At boot the instance downloads the release from this site over HTTPS and verifies its SHA-256 checksum against the value pinned in the template before installing.
2. Collect the outputs
When the stack reaches CREATE_COMPLETE, open its Outputs tab:
ApiEndpoint: the API base URL for your applications.ConsoleUrl: the browser console (/_console).LicenseStatusUrl: license status. It needs an API key with themonitororadminaction (see step 3).AdminKeySecretConsoleUrl: opens the Secrets Manager secret that holds the bootstrap administrator API key.BucketName,InstanceId,LogGroupName: your data bucket, the server, and its logs.LoadBalancerDnsName(HTTPS only): point yourDomainNameat this with a CNAME or alias record.
Check that the server is up. /health needs no credentials:
curl -s <ApiEndpoint>/health
License status needs credentials. Use the administrator key from step 3:
curl -s -H 'Authorization: ApiKey <key_id>:<secret>' <ApiEndpoint>/_license
3. Sign in to the console
- Open
AdminKeySecretConsoleUrland choose Retrieve secret value. The secret holdskey_id,secretand a ready-madeauthorizationheader. The key ID is filled in on first boot, so wait until the server is ready. - Open
ConsoleUrland connect with that administrator credential. The console holds it only in browser memory, never in local storage or cookies. - Treat the admin credential as break-glass. Use it to create the credentials you actually need, then store it away.
4. Create an API key for your application
In the console, open Roles & API keys. Create a role that grants read and write on your index pattern, such as articles*, then create an API key with that role. The key's secret is shown once, so copy it immediately.
You can do the same over HTTP:
curl -sX POST <ApiEndpoint>/_security/apikey \
-H 'Authorization: ApiKey <admin_key_id>:<admin_secret>' \
-H 'Content-Type: application/json' \
-d '{"name": "my-app", "roles": ["articles-writer"]}'
# {"key_id":"…","secret":"…","authorization":"ApiKey <key_id>:<secret>", …}
5. Connect with opensearch-py
from opensearchpy import OpenSearch
client = OpenSearch(
hosts=["<ApiEndpoint>"],
headers={"Authorization": "ApiKey <key_id>:<secret>"},
)
print(client.info()) # distribution "opensearch", version 3.5.0
client.indices.create(index="articles", body={
"mappings": {"properties": {
"title": {"type": "text"},
"body": {"type": "text"},
"published": {"type": "date"},
}}
})
client.index(index="articles", id="1", refresh="wait_for", body={
"title": "Hello", "body": "Search that lives in object storage.",
"published": "2026-09-27T00:00:00Z",
})
hits = client.search(index="articles", body={"query": {"match": {"body": "object storage"}}})
print(hits["hits"]["hits"])
Mappings are strict, so every field must be declared. Before porting existing queries, read the compatibility matrix.
Upgrade
Update the stack with the current template, and change Version and ReleaseSha256 to the new release. Its checksum is published at https://search.avanttechnologiesllc.com/releases/<Version>/. The instance installs the new release and recovers its state from the bucket.
CloudFormation starts the new instance before it terminates the old one. The two servers never both write: every partition has one fenced owner. While the old server still owns a partition, writes to the new one return 503 with Retry-After: 2, which OpenSearch clients retry. When the old instance shuts down it hands ownership over immediately. Searches keep working throughout. Genuine version conflicts are still 409.
Uninstall
Delete the stack. The data bucket is retained with all your data. Delete it yourself in the S3 console if you no longer need it. S3 storage keeps accruing charges until you do.
Troubleshooting
- Cannot connect: confirm your current public IP is inside
AllowedCidr, and that you are using port 8080 when no load balancer is configured. - 403 with
license_…: checkGET /_licensewith an administrator or monitor API key. See Licensing for what each state means. - Server logs: in the
LogGroupNameCloudWatch log group, or on the instance through SSM Session Manager.